-
1
class Card
-
1
class LazyTab < Tab
-
1
def url
-
94
@url ||= (config_hash? && @config[:path]) || format.path(view: view)
-
end
-
-
1
def view
-
15
@view ||= (config_hash? && @config[:view]) || @config
-
end
-
-
1
def tab_button
-
47
if url
-
47
super
-
else
-
wrap_with(:li, label, role: "presentation")
-
end
-
end
-
-
1
def button_attrib
-
141
@button_attrib ||= super.merge("data-url" => url.html_safe)
-
end
-
-
1
def tab_button_link
-
47
add_class button_attrib, "load" unless active?
-
47
super
-
end
-
-
1
def content
-
47
@content ||= ""
-
end
-
-
1
def tab_pane args=nil, &block
-
47
@content = yield if active? && block_given?
-
47
super
-
end
-
end
-
end
-
1
class Card
-
1
class Tab
-
1
attr_reader :format, :name, :label, :content, :button_attrib
-
-
1
class << self
-
1
def tab_objects format, tab_hash, active_name, klass=nil
-
29
klass ||= Card::Tab
-
29
active_name ||= tab_hash.keys.first
-
29
tab_hash.map do |name, config|
-
103
klass.new format, name, active_name, config
-
end
-
end
-
end
-
-
1
delegate :add_class, :wrap_with, :unique_id, :link_to, to: :format
-
-
1
def initialize format, name, active_name, config
-
103
@format = format
-
103
@name = name
-
103
@active_name = active_name
-
103
@config = config
-
end
-
-
1
def tab_button
-
103
add_class button_attrib, "active" if active?
-
103
wrap_with :li, tab_button_link,
-
role: :presentation,
-
class: "nav-item tab-li-#{name}"
-
end
-
-
1
def tab_pane args=nil
-
103
pane_attr = { role: :tabpanel, id: tab_id }
-
103
pane_attr.merge! args if args.present?
-
103
add_class pane_attr, "tab-pane tab-pane-#{name}"
-
103
add_class pane_attr, "active" if active?
-
103
wrap_with :div, content, pane_attr
-
end
-
-
1
private
-
-
1
def config_hash?
-
324
@config.is_a? Hash
-
end
-
-
1
def label
-
103
@label ||= (config_hash? && @config[:title]) || name
-
end
-
-
1
def content
-
56
@content ||= config_hash? ? @config[:content] : @config
-
end
-
-
1
def button_attrib
-
174
@button_attrib ||= (config_hash? && @config[:button_attr]) || {}
-
end
-
-
1
def tab_button_link
-
103
add_class button_attrib, "nav-link"
-
-
103
link_to label, button_attrib.merge(
-
path: "##{tab_id}",
-
role: "tab",
-
"data-toggle" => "tab",
-
"data-tab-name" => name
-
)
-
end
-
-
1
def tab_id
-
206
@tab_id ||= "#{unique_id}-#{name.to_name.safe_key}"
-
end
-
-
1
def active?
-
300
name == @active_name
-
end
-
end
-
end
-
1
class Card
-
# stash followers of a given card
-
1
class FollowerStash
-
1
def initialize card=nil
-
112
@stash = Hash.new { |h, v| h[v] = [] }
-
54
@checked = ::Set.new
-
54
check_card(card) if card
-
end
-
-
1
def check_card card
-
94
return if @checked.include? card.key
-
-
92
Auth.as_bot do
-
92
@checked.add card.key
-
92
stash_direct_followers card
-
92
stash_field_followers card.left
-
end
-
end
-
-
1
def followers
-
@stash.keys
-
end
-
-
1
def each_follower_with_reason
-
# "follower"(=user) is a card object, "followed"(=reasons) a card name
-
54
@stash.each do |follower_card, reasons|
-
58
yield(follower_card, reasons.first)
-
end
-
end
-
-
1
private
-
-
1
def stash_direct_followers card
-
92
card.each_direct_follower_id_with_reason do |user_id, reason|
-
61
stash Card.fetch(user_id), reason
-
end
-
end
-
-
1
def stash_field_followers card
-
92
return unless (fields = follow_fields card)
-
-
31
fields.each do |field|
-
38
break if stash_field_follower card, field
-
end
-
end
-
-
1
def stash_field_follower card, field
-
38
return false unless checked?(field.to_name) || nested?(card, field)
-
-
7
check_card card
-
7
true
-
end
-
-
1
def nested? card, field
-
35
return unless field.to_name.key == includes_card_key
-
-
30
@checked.intersection(nestee_set(card)).any?
-
end
-
-
1
def includes_card_key
-
35
@includes_card_key ||= :nests.cardname.key
-
end
-
-
1
def nestee_set card
-
30
@nestee_set ||= {}
-
30
@nestee_set[card.key] ||= nestee_search card
-
end
-
-
1
def nestee_search card
-
30
Card.search({ return: "key", included_by: card.name },
-
"follow cards included by #{card.name}")
-
end
-
-
1
def checked? name
-
83
@checked.include? name.key
-
end
-
-
1
def follow_fields card
-
92
return unless card && !checked?(card.name)
-
-
31
card.rule_card(:follow_fields)&.item_names(context: card.name)
-
end
-
-
1
def stash follower, reason
-
61
@stash[follower] << reason
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# An "act" is a group of recorded {Card::Action actions} on {Card cards}.
-
# Together, {Act acts}, {Action actions}, and {Change changes} comprise a
-
# comprehensive {Card card} history tracking system.
-
#
-
# For example, if a given web form submissions updates the contents of three cards,
-
# then the submission will result in the recording of three {Action actions}, each
-
# of which is tied to one {Act act}.
-
#
-
# Each act records:
-
#
-
# - the _actor_id_ (an id associated with the account responsible)
-
# - the _card_id_ of the act's primary card
-
# - _acted_at_, a timestamp of the action
-
# - the _ip_address_ of the actor where applicable.
-
#
-
1
class Act < ApplicationRecord
-
1
before_save :assign_actor
-
2519
has_many :ar_actions, -> { order :id }, foreign_key: :card_act_id,
-
inverse_of: :act,
-
class_name: "Card::Action"
-
1
class << self
-
# remove all acts that have no card. (janitorial)
-
#
-
# CAREFUL - could still have actions even if act card is gone...
-
1
def delete_cardless
-
left_join = "LEFT JOIN cards ON card_acts.card_id = cards.id"
-
joins(left_join).where("cards.id IS NULL").delete_all
-
end
-
-
# remove all acts that have no action. (janitorial)
-
1
def delete_actionless
-
2
joins(
-
"LEFT JOIN card_actions ON card_acts.id = card_act_id"
-
).where(
-
"card_actions.id is null"
-
).delete_all
-
end
-
-
# all acts with actions on a given list of cards
-
# @param card_ids [Array of Integers]
-
# @param with_drafts [true, false] (only shows drafts of current user)
-
# @return [Array of Acts]
-
1
def all_with_actions_on card_ids, with_drafts=false
-
3
sql = "card_actions.card_id IN (:card_ids) AND (draft is not true"
-
3
sql << (with_drafts ? " OR actor_id = :user_id)" : ")")
-
3
all_viewable([sql, { card_ids: card_ids, user_id: Card::Auth.current_id }])
-
end
-
-
# all acts with actions that current user has permission to view
-
# @return [ActiveRecord Relation]
-
1
def all_viewable action_where=nil
-
3
relation = joins(ar_actions: :ar_card)
-
3
relation = relation.where(action_where) if action_where
-
3
relation.where(Query::CardQuery.viewable_sql).where.not(card_id: nil).distinct
-
end
-
-
1
def cache
-
362
Card::Cache[Card::Act]
-
end
-
-
# used by rails time_ago
-
# timestamp is set by rails on create
-
1
def timestamp_attributes_for_create
-
1
super << "acted_at"
-
end
-
end
-
-
1
def actor
-
65
Card.fetch actor_id
-
end
-
-
# the act's primary card
-
# @return [Card]
-
1
def card
-
94
Card.fetch card_id, look_in_trash: true # , skip_modules: true
-
-
# FIXME: if the following is necessary, we need to document why.
-
# generally it's a very bad idea to have type-specific code here.
-
-
# return res unless res&.type_id&.in?([Card::FileID, Card::ImageID])
-
# res.include_set_modules
-
end
-
-
# list of all actions that are part of the act
-
# @return [Array]
-
1
def actions cached=true
-
416
return ar_actions unless cached
-
-
412
self.class.cache.fetch("#{id}-actions") { ar_actions.find_all.to_a }
-
end
-
-
# act's action on the card in question
-
# @param card_id [Integer]
-
# @return [Card::Action]
-
1
def action_on card_id
-
153
actions.find do |action|
-
153
action.card_id == card_id && !action.draft
-
end
-
end
-
-
# act's action on primary card if it exists. otherwise act's first action
-
# @return [Card::Action]
-
1
def main_action
-
152
action_on(card_id) || actions.first
-
end
-
-
1
def draft?
-
2
main_action.draft
-
end
-
-
# time (in words) since act took place
-
# @return [String]
-
1
def elapsed_time
-
DateTime.new(acted_at).distance_of_time_in_words_to_now
-
end
-
-
# act's actions on either the card itself or another card that includes it
-
# @param card [Card]
-
# @return [Array of Actions]
-
1
def actions_affecting card
-
150
actions.select do |action|
-
223
(card.id == action.card_id) ||
-
card.nestee_ids.include?(action.card_id)
-
end
-
end
-
-
1
private
-
-
# used by before filter
-
1
def assign_actor
-
2455
self.actor_id ||= Auth.current_id
-
end
-
end
-
end
-
1
class Card
-
1
class Act
-
1
class ActRenderer
-
1
def initialize format, act, args
-
4
@format = format
-
4
@act = act
-
4
@act_card = act.card
-
4
@args = args
-
4
@card = @format.card
-
4
@context = @args[:act_context]
-
end
-
-
1
include ::Bootstrapper
-
-
1
def method_missing method_name, *args, &block
-
56
if block_given?
-
8
@format.send(method_name, *args, &block)
-
else
-
48
@format.send(method_name, *args)
-
end
-
end
-
-
1
def respond_to_missing? method_name, _include_private=false
-
@format.respond_to? method_name
-
end
-
-
1
def render
-
3
return "" unless @act_card
-
-
3
act_accordion
-
end
-
-
1
def header
-
#::Bootstrap.new(self).render do
-
3
bs_layout do
-
3
row xs: [10, 2] do
-
3
column do
-
3
html title
-
6
tag(:span, "text-muted pl-1 badge") { summary }
-
end
-
3
column act_links, class: "text-right"
-
end
-
end
-
# end
-
end
-
-
1
def absolute_title
-
1
accordion_expand_link(@act_card.name)
-
end
-
-
1
def details
-
3
approved_actions[0..20].map do |action|
-
3
Action::ActionRenderer.new(@format, action, action_header?,
-
:summary).render
-
end.join
-
end
-
-
1
def summary
-
4
%i[create update delete draft].map do |type|
-
16
next unless count_types[type].positive?
-
-
4
"#{@format.action_icon type}<small> #{count_types[type]}</small>"
-
end.compact.join "<small class='text-muted'> | </small>"
-
end
-
-
1
def act_links
-
[
-
1
link_to_history,
-
1
(link_to_act_card unless @act_card.trash)
-
].compact.join " "
-
end
-
-
1
def link_to_act_card
-
1
link_to_card @act_card, icon_tag(:new_window), class: "_stop_propagation"
-
end
-
-
1
def link_to_history
-
1
link_to_card @act_card, icon_tag(:history),
-
path: { view: :history, look_in_trash: true },
-
class: "_stop_propagation",
-
rel: "nofollow"
-
end
-
-
1
def approved_actions
-
11
@approved_actions ||= actions.select { |a| a.card&.ok?(:read) }
-
# FIXME: should not need to test for presence of card here.
-
end
-
-
1
def action_header?
-
3
true
-
# @action_header ||= approved_actions.size != 1 ||
-
# approved_actions[0].card_id != @format.card.id
-
end
-
-
1
def count_types
-
20
@count_types ||=
-
approved_actions.each_with_object(
-
16
Hash.new { |h, k| h[k] = 0 }
-
) do |action, type_cnt|
-
4
type_cnt[action.action_type] += 1
-
end
-
end
-
-
1
def edited_ago
-
4
return "" unless @act.acted_at
-
-
4
"#{time_ago_in_words(@act.acted_at)} ago"
-
end
-
-
1
def collapse_id
-
16
"act-id-#{@act.id}"
-
end
-
-
1
def accordion_expand_link text
-
3
<<-HTML
-
<a>
-
#{text}
-
</a>
-
HTML
-
end
-
-
# TODO: change accordion API in bootstrap/helper.rb so that it can be used
-
# here. The problem is that here we have extra links in the title
-
# that are not supposed to expand the accordion
-
1
def act_accordion
-
3
context = @act.main_action.draft ? :warning : :default
-
3
<<-HTML
-
<div class="card card-#{context} nodblclick">
-
#{act_accordion_panel}
-
</div>
-
HTML
-
end
-
-
1
def accordion_expand_options
-
{
-
3
"data-toggle" => "collapse",
-
"data-target" => ".#{collapse_id}",
-
"aria-expanded" => true,
-
"aria-controls" => collapse_id
-
}
-
end
-
-
1
def act_panel_options
-
3
{ class: "card-header", role: "tab", id: "heading-#{collapse_id}" }
-
end
-
-
1
def act_accordion_panel
-
3
act_accordion_heading + act_accordion_body
-
end
-
-
1
def act_accordion_heading
-
3
wrap_with :div, act_panel_options.merge(accordion_expand_options) do
-
3
wrap_with(:h5, header, class: "mb-0") + subtitle
-
end
-
end
-
-
1
def act_accordion_body
-
3
wrap_with :div, id: collapse_id,
-
class: "collapse #{collapse_id}",
-
"data-parent": ".act-accordion-group" do
-
3
wrap_with :div, details, class: "card-body"
-
end
-
end
-
-
# Revert:
-
# current update
-
# Restore:
-
# current deletion
-
# Revert and Restore:
-
# old deletions
-
# blank:
-
# current create
-
# save as current:
-
# not current, not deletion
-
1
def rollback_link
-
1
return unless card.ok? :update
-
-
1
wrap_with :div, class: "act-link collapse #{collapse_id} float-right" do
-
1
content_tag(:small, revert_link)
-
-
# link_to "Save as current",
-
# class: "slotter", remote: true,
-
# method: :post, rel: "nofollow",
-
# "data-slot-selector" => ".card-slot.history-view",
-
# path: { action: :update, action_ids: prior,
-
# view: :open, look_in_trash: true }
-
end
-
end
-
-
1
def deletion_act?
-
act_type == :delete
-
end
-
-
1
def act_type
-
@act.main_action.action_type
-
end
-
-
1
def show_or_hide_changes_link
-
wrap_with :div, class: "act-link" do
-
@format.link_to_view(
-
:act, "#{@args[:hide_diff] ? 'Show' : 'Hide'} changes",
-
path: { act_id: @args[:act].id, act_seq: @args[:act_seq],
-
hide_diff: !@args[:hide_diff], action_view: :expanded,
-
act_context: @args[:act_context], look_in_trash: true }
-
)
-
end
-
end
-
-
1
def autosaved_draft_link opts={}
-
text = opts.delete(:text) || "autosaved draft"
-
opts[:path] = { edit_draft: true }
-
add_class opts, "navbar-link"
-
link_to_view :edit, text, opts
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Act
-
1
class ActRenderer
-
# Used for recent changes.
-
# It shows all actions of an act
-
1
class AbsoluteActRenderer < ActRenderer
-
1
def title
-
1
absolute_title
-
end
-
-
1
def subtitle
-
1
wrap_with :small do
-
[
-
1
@format.link_to_card(@act.actor, nil, class: "_stop_propagation"),
-
edited_ago,
-
rollback_link
-
]
-
end
-
end
-
-
# FIXME: how do we know we need main here??
-
1
def revert_link
-
1
revert_actions_link "revert to previous",
-
{ revert_to: :previous, revert_act: @act.id },
-
"data-slot-selector": "#main > .card-slot"
-
end
-
-
1
def actions
-
1
@act.actions
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Act
-
1
class ActRenderer
-
# Used for the bridge
-
1
class BridgeActRenderer < RelativeActRenderer
-
1
def title
-
1
wrap_with(:div, left_title, class: "mr-2") +
-
wrap_with(:div, right_title, class: "ml-auto act-summary")
-
end
-
-
1
def left_title
-
1
["##{@args[:act_seq]}", @act.actor.name, wrap_with(:small, edited_ago)].join " "
-
end
-
-
1
def right_title
-
1
summary
-
end
-
-
1
def render
-
return "" unless @act_card
-
-
details
-
end
-
-
1
def bridge_link
-
1
opts = @format.bridge_link_opts(
-
path: { act_id: @act.id, view: :bridge_act, act_seq: @args[:act_seq] },
-
"data-toggle": "pill"
-
)
-
1
add_class opts, "d-flex nav-link"
-
1
opts[:path].delete :layout
-
1
link_to_card @card, title, opts
-
end
-
-
1
def overlay_title
-
wrap_with :div do
-
[left_title, summary,
-
subtitle.present? ? subtitle : nil,
-
rollback_or_edit_link].compact.join " | "
-
end
-
end
-
-
1
def rollback_or_edit_link
-
if @act.draft?
-
autosaved_draft_link text: "continue editing"
-
elsif show_rollback_link?
-
revert_link
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Act
-
1
class ActRenderer
-
# Use for the history for one specific card
-
# It shows only the actions of an act that are relevant
-
# for the card of the format that renders the act.
-
1
class RelativeActRenderer < ActRenderer
-
1
def title
-
2
"<span class=\"nr\">##{@args[:act_seq]}</span>" +
-
accordion_expand_link(@act.actor.name) +
-
" " +
-
wrap_with(:small, edited_ago)
-
end
-
-
1
def subtitle
-
2
return "" unless @act.card_id != @format.card.id
-
-
wrap_with :small, "act on #{absolute_title}"
-
end
-
-
1
def act_links
-
2
return unless (content = rollback_or_edit_link)
-
-
wrap_with :small, content
-
end
-
-
1
def rollback_or_edit_link
-
2
if @act.draft?
-
autosaved_draft_link text: "continue editing",
-
class: "collapse #{collapse_id}"
-
2
elsif show_rollback_link?
-
rollback_link
-
end
-
end
-
-
1
def show_rollback_link?
-
2
!current_act?
-
end
-
-
1
def current_act?
-
2
return unless @format.card.last_act && @act
-
-
2
@act.id == @format.card.last_act.id
-
end
-
-
1
def actions
-
3
@actions ||= @act.actions_affecting(@card)
-
end
-
-
1
def revert_link
-
revert_actions_link "revert to this",
-
{ revert_actions: actions.map(&:id) },
-
class: "_close-modal",
-
"data-slotter-mode": "update-modal-origin"
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# An _action_ is a group of {Card::Change changes} to a single {Card card}
-
# that is recorded during an {Card::Act act}.
-
# Together, {Act acts}, {Action actions}, and {Change changes} comprise a
-
# comprehensive {Card card} history tracking system.
-
#
-
# For example, if a given web submission changes both the name and type of
-
# a given card, that would be recorded as one {Action action} with two
-
# {Change changes}. If there are multiple cards changed, each card would
-
# have its own {Action action}, but the whole submission would still comprise
-
# just one single {Act act}.
-
#
-
# An {Action} records:
-
#
-
# * the _card_id_ of the {Card card} acted upon
-
# * the _card_act_id_ of the {Card::Act act} of which the action is part
-
# * the _action_type_ (create, update, or delete)
-
# * a boolean indicated whether the action is a _draft_
-
# * a _comment_ (where applicable)
-
#
-
1
class Action < ApplicationRecord
-
1
include Differ
-
1
extend Admin
-
-
1
belongs_to :act, foreign_key: :card_act_id, inverse_of: :ar_actions
-
1
belongs_to :ar_card, foreign_key: :card_id, inverse_of: :actions, class_name: "Card"
-
1
has_many :card_changes, foreign_key: :card_action_id,
-
inverse_of: :action,
-
dependent: :delete_all,
-
class_name: "Card::Change"
-
1
belongs_to :super_action, class_name: "Action", inverse_of: :sub_actions
-
1
has_many :sub_actions, class_name: "Action", inverse_of: :super_action
-
-
1
scope :created_by, lambda { |actor_id|
-
2546
joins(:act).where "card_acts.actor_id = ?", actor_id
-
}
-
-
# these are the three possible values for action_type
-
1
TYPE_OPTIONS = %i[create update delete].freeze
-
-
1
after_save :expire
-
-
1
class << self
-
# retrieve action from cache if available
-
# @param id [id of Action]
-
# @return [Action, nil]
-
1
def fetch id
-
37
cache.fetch id.to_s do
-
18
find id.to_i
-
end
-
end
-
-
# cache object for actions
-
# @return [Card::Cache]
-
1
def cache
-
5349
Card::Cache[Action]
-
end
-
-
1
def all_with_cards
-
joins :ar_card
-
end
-
-
1
def all_viewable
-
all_with_cards.where Query::CardQuery.viewable_sql
-
end
-
end
-
-
# each action is associated with on and only one card
-
# @return [Card]
-
1
def card
-
1122
Card.fetch card_id, look_in_trash: true
-
-
# I'm not sure what the rationale for the following was/is, but it was causing
-
# problems in cases where slot attributes are overridden (eg see #wrap_data in
-
# sources on wikirate). The problem is the format object had the set modules but
-
# the card didn't.
-
#
-
# My guess is that the need for the following had something to do with errors
-
# associated with changed types. If so, the solution probably needs to handle
-
# including the set modules associated with the type at the time of the action
-
# rather than including no set modules at all.
-
#
-
# What's more, we _definitely_ don't want to hard code special behavior for
-
# specific types in here!
-
-
# , skip_modules: true
-
# return res unless res && res.type_id.in?([Card::FileID, Card::ImageID])
-
# res.include_set_modules
-
end
-
-
# remove action from action cache
-
1
def expire
-
4525
self.class.cache.delete id.to_s
-
end
-
-
# assign action_type (create, update, or delete)
-
# @param value [Symbol]
-
# @return [Integer]
-
1
def action_type= value
-
2300
write_attribute :action_type, TYPE_OPTIONS.index(value)
-
end
-
-
# retrieve action_type (create, update, or delete)
-
# @return [Symbol]
-
1
def action_type
-
5124
return :draft if draft
-
-
5124
TYPE_OPTIONS[read_attribute(:action_type)]
-
end
-
-
1
def previous_action
-
4
Card::Action.where("id < ? AND card_id = ?", id, card_id).last
-
end
-
-
# value set by action's {Change} to given field
-
# @see #interpret_field #interpret_field for field param
-
# @see #interpret_value #interpret_value for return values
-
1
def value field
-
743
return unless (change = change field)
-
-
568
interpret_value field, change.value
-
end
-
-
# value of field set by most recent {Change} before this one
-
# @see #interpret_field #interpret_field for field param
-
# @see #interpret_field #interpret_field for field param
-
1
def previous_value field
-
27
return if action_type == :create
-
3
return unless (previous_change = previous_change field)
-
-
3
interpret_value field, previous_change.value
-
end
-
-
# action's {Change} object for given field
-
# @see #interpret_field #interpret_field for field param
-
# @return [Change]
-
1
def change field
-
763
changes[interpret_field field]
-
end
-
-
# most recent change to given field before this one
-
# @see #interpret_field #interpret_field for field param
-
# @return [Change]
-
1
def previous_change field
-
3
return nil if action_type == :create
-
-
3
field = interpret_field field
-
3
if @previous_changes&.key?(field)
-
@previous_changes[field]
-
else
-
3
@previous_changes ||= {}
-
3
@previous_changes[field] = card.last_change_on field, before: self
-
end
-
end
-
-
1
def all_changes
-
313
self.class.cache.fetch("#{id}-changes") do
-
# using card_changes causes caching problem
-
123
Card::Change.where(card_action_id: id).to_a
-
end
-
end
-
-
# all action {Change changes} in hash form. { field1: Change1 }
-
# @return [Hash]
-
1
def changes
-
766
@changes ||=
-
209
if sole?
-
107
current_changes
-
else
-
102
all_changes.each_with_object({}) do |change, hash|
-
149
hash[change.field.to_sym] = change
-
end
-
end
-
end
-
-
# all changed values in hash form. { field1: new_value }
-
1
def changed_values
-
3
@changed_values ||= changes.each_with_object({}) do |(key, change), h|
-
18
h[key] = change.value
-
end
-
end
-
-
# @return [Hash]
-
1
def current_changes
-
107
return {} unless card
-
-
107
@current_changes ||=
-
Card::Change::TRACKED_FIELDS.each_with_object({}) do |field, hash|
-
642
hash[field.to_sym] = Card::Change.new field: field,
-
value: card.send(field),
-
card_action_id: id
-
end
-
end
-
-
# translate field into fieldname as referred to in database
-
# @see Change::TRACKED_FIELDS
-
# @param field [Symbol] can be :type_id, :cardtype, :db_content, :content,
-
# :name, :trash
-
# @return [Symbol]
-
1
def interpret_field field
-
766
case field
-
125
when :content then :db_content
-
121
when :cardtype then :type_id
-
520
else field.to_sym
-
end
-
end
-
-
# value in form prescribed for specific field name
-
# @param value [value of {Change}]
-
# @return [Integer] for :type_id
-
# @return [String] for :name, :db_content, :content, :cardtype
-
# @return [True/False] for :trash
-
1
def interpret_value field, value
-
571
case field.to_sym
-
when :type_id
-
6
value&.to_i
-
when :cardtype
-
57
Card.fetch_name(value&.to_i)
-
508
else value
-
end
-
end
-
-
1
def sole?
-
211
all_changes.empty? &&
-
119
(action_type == :create || Card::Action.where(card_id: card_id).count == 1)
-
end
-
end
-
end
-
1
class Card
-
1
class Action
-
1
class ActionRenderer
-
1
attr_reader :action, :header
-
1
def initialize format, action, header=true, action_view=:summary, hide_diff=false
-
3
@format = format
-
3
@action = action
-
3
@header = header
-
3
@action_view = action_view
-
3
@hide_diff = hide_diff
-
end
-
-
1
include ::Bootstrapper
-
1
def method_missing method_name, *args, &block
-
33
if block_given?
-
@format.send(method_name, *args, &block)
-
else
-
33
@format.send(method_name, *args)
-
end
-
end
-
-
1
def respond_to_missing? method_name, _include_private=false
-
@format.respond_to? method_name
-
end
-
-
1
def render
-
3
classes = @format.classy("action-list")
-
3
bs_layout container: true, fluid: true do
-
3
row do
-
3
html <<-HTML
-
<ul class="#{classes} w-100">
-
<li class="#{action.action_type}">
-
#{action_panel}
-
</li>
-
</ul>
-
HTML
-
end
-
end
-
end
-
-
1
def action_panel
-
3
bs_panel do
-
3
if header
-
3
heading do
-
3
div type_diff, class: "float-right"
-
3
div name_diff
-
end
-
end
-
3
body do
-
3
content_diff
-
end
-
end
-
end
-
-
1
def name_diff
-
3
if @action.card == @format.card
-
3
name_changes
-
else
-
link_to_view(
-
:related, name_changes,
-
path: { slot: { items: { view: "history", nest_name: @action.card.name } } },
-
# "data-slot-selector" => ".card-slot.history-view"
-
)
-
end
-
end
-
-
1
def content_diff
-
3
return @action.raw_view if @action.action_type == :delete
-
-
3
@format.subformat(@action.card).render_action_summary action_id: @action.id
-
end
-
-
1
def type_diff
-
3
return "" unless @action.new_type?
-
-
3
@hide_diff ? @action.value(:cardtype) : @action.cardtype_diff
-
end
-
-
1
def name_changes
-
3
return old_name unless @action.new_name?
-
-
3
@hide_diff ? new_name : Card::Content::Diff.complete(old_name, new_name)
-
end
-
-
1
def old_name
-
3
(name = @action.previous_value :name) && title_in_context(name)
-
end
-
-
1
def new_name
-
3
title_in_context @action.value(:name)
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Action
-
# methods for administering card actions
-
1
module Admin
-
# permanently delete all {Action actions} not associated with a {Card}
-
1
def delete_cardless
-
1
left_join = "LEFT JOIN cards ON card_actions.card_id = cards.id"
-
1
joins(left_join).where("cards.id IS NULL").delete_all
-
end
-
-
# permanently delete all {Action actions} associate with non-current
-
# {Change changes}
-
1
def delete_old
-
1
Card::Change.delete_all
-
1
Card.find_each(&:delete_old_actions)
-
1
Card::Act.delete_actionless
-
end
-
-
# If an act is given then all remaining actions will be attached to that act.
-
# Otherwise the actions keep their acts.
-
1
def make_current_state_the_initial_state act=nil
-
Card::Change.delete_all
-
Card.find_each(&:delete_old_actions)
-
action_update = { action_type: Card::Action::TYPE_OPTIONS.index(:create) }
-
action_update[:card_act_id] = act.id if act
-
Card::Action.update_all action_update
-
-
if act
-
Card::Act.where("id != :id", id: act.id).delete_all
-
else
-
Card::Act.delete_actionless
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Action
-
# a collection of methods for comparing actions
-
1
module Differ
-
# compare action's name value with previous name value
-
# @return [rendered diff]
-
1
def name_diff opts={}
-
return unless new_name?
-
-
diff_object(:name, opts).complete
-
end
-
-
# does action change card's name?
-
# @return [true/false]
-
1
def new_name?
-
3
!value(:name).nil?
-
end
-
-
# @return [rendered diff]
-
# compare action's cardtype value with previous cardtype value
-
1
def cardtype_diff opts={}
-
3
return unless new_type?
-
-
3
diff_object(:cardtype, opts).complete
-
end
-
-
# does action change card's type?
-
# @return [true/false]
-
1
def new_type?
-
6
!value(:type_id).nil?
-
end
-
-
# @return [rendered diff]
-
# compare action's content value with previous content value
-
1
def content_diff diff_type=:expanded, opts=nil
-
5
return unless new_content?
-
-
5
dobj = content_diff_object(opts)
-
5
diff_type == :summary ? dobj.summary : dobj.complete
-
end
-
-
# does action change card's content?
-
# @return [true/false]
-
1
def new_content?
-
388
!value(:db_content).nil?
-
end
-
-
# test whether content was visibly removed
-
# @return [true/false]
-
1
def red?
-
content_diff_object.red?
-
end
-
-
# test whether content was visibly added
-
# @return [true/false]
-
1
def green?
-
content_diff_object.green?
-
end
-
-
1
def raw_view content=nil
-
6
original_content = card.db_content
-
6
card.db_content = content || value(:db_content)
-
6
card.format.render_raw
-
ensure
-
6
card.db_content = original_content
-
end
-
-
1
def summary_diff_omits_content?
-
5
content_diff_object.summary_omits_content?
-
end
-
-
1
private
-
-
1
def diff_object field, opts
-
3
Card::Content::Diff.new previous_value(field), value(field), opts
-
end
-
-
1
def content_diff_object opts=nil
-
10
@diff ||= begin
-
5
diff_args = opts || card.include_set_modules.diff_args
-
5
previous_value = previous_value(:content)
-
5
previous = previous_value ? raw_view(previous_value) : ""
-
5
current = raw_view
-
5
Card::Content::Diff.new previous, current, diff_args
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
1
require 'activerecord-import'
-
-
1
class Card
-
# A _change_ is an alteration to a card's name, type, content, or trash state.
-
# Together, {Act acts}, {Action actions}, and {Change changes} comprise a
-
# comprehensive {Card card} history tracking system.
-
#
-
# For example, if a given web submission changes both the name and type of
-
# card, that would be recorded as one {Action action} with two
-
# {Change changes}.
-
#
-
# A {Change} records:
-
#
-
# * the _field_ changed
-
# * the new _value_ of that field
-
# * the {Action action} of which the change is part
-
#
-
1
class Change < ApplicationRecord
-
1
belongs_to :action, foreign_key: :card_action_id,
-
inverse_of: :card_changes
-
-
# lists the database fields for which changes are recorded
-
1
TRACKED_FIELDS = %w[name type_id db_content trash left_id right_id].freeze
-
-
1
class << self
-
# delete all {Change changes} not associated with an {Action action}
-
# (janitorial)
-
1
def delete_actionless
-
1
joins(
-
"LEFT JOIN card_actions "\
-
"ON card_changes.card_action_id = card_actions.id "
-
).where(
-
"card_actions.id is null"
-
).pluck_in_batches(:id) do |group_ids|
-
# used to be .delete_all here, but that was failing on large dbs
-
1
Rails.logger.info "deleting batch of changes"
-
1
where("id in (#{group_ids.join ','})").delete_all
-
end
-
end
-
-
# Change fields are recorded as integers. #field_index looks up the
-
# integer associated with a given field name.
-
# @param value [String, Symbol]
-
# @return [Integer]
-
1
def field_index value
-
8
value.is_a?(Integer) ? value : TRACKED_FIELDS.index(value.to_s)
-
end
-
-
# look up changes based on field name
-
# @param value [String, Symbol]
-
# @return [Change]
-
1
def find_by_field_name value
-
find_by_field field_index(value)
-
end
-
end
-
-
# set field value (integer)
-
# @param value [String, Symbol]
-
1
def field= value
-
4080
write_attribute(:field, TRACKED_FIELDS.index(value.to_s))
-
end
-
-
# retrieve field name
-
# @return [String]
-
1
def field
-
150
TRACKED_FIELDS[read_attribute(:field)]
-
end
-
end
-
end
-
1
class Card
-
1
module Machine
-
1
REFRESHED = "MACHINE_ASSETS_REFRESHED".freeze
-
-
1
class << self
-
1
def refresh_script_and_style
-
37
return unless refresh_script_and_style?
-
Card.fetch(:all, :script)&.update_if_source_file_changed
-
Card.fetch(:all, :style)&.update_if_source_file_changed
-
end
-
-
1
private
-
-
1
def refresh_script_and_style?
-
37
case Cardio.config.machine_refresh
-
when :eager then true
-
when :cautious then cautious_refresh?
-
37
when :never then false
-
else
-
raise Card::Error,
-
"unknown option for machine_refresh: #{Cardio.config.machine_refresh}"
-
end
-
end
-
-
# only refresh when cache was cleared
-
1
def cautious_refresh?
-
return false unless Card::Cache.persistent_cache
-
return false if Card.cache.read REFRESHED
-
Card.cache.write REFRESHED, true
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Reference
-
# Extracts all information needed to generate the nest editor form
-
# from a nest syntax string
-
1
class NestParser
-
1
NEST_OPTIONS = %i[view title show hide wrap help variant size params].freeze
-
-
1
attr_reader :name, :options, :item_options, :raw
-
-
1
def self.new nest_string, default_view, default_item_view
-
14
return super if nest_string.is_a? String
-
-
5
OpenStruct.new(name: "", field?: true,
-
options: [[:view, default_view]], item_options: [],
-
raw: "{{+|view: #{default_view}}}")
-
end
-
-
1
def self.new_image name
-
5
OpenStruct.new(name: name, field?: true,
-
options: [%i[view content], %i[size medium]],
-
item_options: [],
-
raw: "{{+#{name}|view: content; size: medium}}")
-
end
-
-
1
def field?
-
6
@field
-
end
-
-
1
def initialize nest_string, _default_view, default_item_view
-
9
@raw = nest_string
-
9
@default_item_view = default_item_view
-
9
nest = Card::Content::Chunk::Nest.new nest_string, nil
-
9
init_name nest.name
-
9
extract_item_options nest.options
-
9
@options = extract_options nest.options
-
end
-
-
1
private
-
-
1
def init_name name
-
9
@field = name.to_name.simple_relative?
-
9
@name = @field ? name.to_s[1..-1] : name
-
end
-
-
1
def extract_options options
-
21
Card::Reference::NestParser::NEST_OPTIONS.each_with_object([]) do |key, res|
-
189
next unless options[key]
-
-
42
if key.in? %i[show hide]
-
13
values = Card::View.normalize_list(options[key])
-
36
res.concat(values.map { |val| [key, val] })
-
else
-
29
res << [key, options[key]]
-
end
-
end
-
end
-
-
1
def extract_item_options options
-
9
@item_options = []
-
9
item_options = options[:items]
-
9
while item_options
-
12
next_item_options = item_options[:items]
-
12
@item_options << extract_options(item_options)
-
12
item_options = next_item_options
-
end
-
# @item_options << default_item_options
-
end
-
-
1
def default_item_options
-
[:view, @default_item_view]
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# Model for the card_virtuals table.
-
# It provides method to get and store content for virtual cards from
-
# the card_virtuals table.
-
1
class Virtual < ApplicationRecord
-
1
def update new_content
-
68
update! content: new_content
-
68
new_content
-
end
-
-
1
class << self
-
1
def create card, virtual_content=nil
-
152
validate_card card
-
152
virtual_content ||= block_given? ? yield : card.generate_virtual_content
-
152
virtual = new left_id: left_id(card), right_id: right_id(card),
-
left_key: card.name.left_key,
-
content: virtual_content
-
152
virtual.save!
-
152
virtual
-
end
-
-
1
def create_or_update card, virtual_content
-
73
if (virtual_card = find_by_card(card))
-
67
virtual_card.update virtual_content
-
else
-
6
create card, virtual_content
-
end
-
end
-
-
1
def fetch_content card, &block
-
184
find_content_by_card(card) || create(card, &block).content
-
end
-
-
1
def fetch card, &block
-
find_by_card(card) || create(card, &block)
-
end
-
-
1
def refresh card
-
1
virtual = find_by_card(card)
-
1
return create(card) unless virtual
-
1
virtual.update card.generate_virtual_content
-
end
-
-
1
def find_content_by_card card
-
184
where_card(card)&.pluck(:content)&.first
-
end
-
-
1
def find_by_card card
-
77
where_card(card).take
-
end
-
-
1
private
-
-
1
def where_card card
-
261
query = { right_id: right_id(card) }
-
261
if (lid = left_id(card))
-
47
query[:left_id] = lid
-
else
-
214
query[:left_key] = card.name.left_key
-
end
-
261
where query
-
end
-
-
1
def left_id card
-
565
if card.junction?
-
565
card.left_id&.positive? ? card.left_id : card.left&.id
-
else
-
card.id
-
end
-
end
-
-
1
def right_id card
-
565
if card.junction?
-
565
card.right_id&.positive? ? card.right_id : card.right&.id
-
else
-
-2
-
end
-
end
-
-
1
def validate_card card
-
152
reason ||=
-
152
if card.junction?
-
152
"needs left_id" unless left_id(card)
-
152
"needs right_id" unless right_id(card)
-
elsif !card.id
-
"needs id"
-
end
-
152
return unless reason
-
raise Card::Error, card.name, "count not cacheable: card #{card.name} #{reason}"
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# Singleton methods for account authentication and contextualization.
-
#
-
# Manages current user,
-
# "as" user, and password verification.
-
1
module Auth
-
1
extend Permissions
-
1
extend Proxy
-
1
extend Setup
-
1
extend Current
-
-
1
@as_card = @as_id = @current_id = @current = nil
-
-
1
class << self
-
# authenticate a user by their login name and unencrypted password.
-
# @param email [String]
-
# @param password [String]
-
# @return [+*account card, nil]
-
1
def authenticate email, password
-
9
account = Auth.find_account_by_email email
-
case
-
10
when !account then nil
-
when !account.active? then nil
-
when Card.config.no_authentication then account
-
7
when password_valid?(account, password.strip) then account
-
end
-
end
-
-
# check whether password is correct for account card
-
# @param account [+*account card]
-
# @param password [String]
-
1
def password_valid? account, password
-
9
account.password == encrypt(password, account.salt)
-
end
-
-
# encrypt password string with the given salt.
-
# @return [SHA1 String]
-
1
def encrypt password, salt
-
27
Digest::SHA1.hexdigest "#{salt}--#{password}--"
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Auth
-
# methods for setting current account
-
1
module Current
-
# set current user in process and session
-
1
def signin cardish
-
2112
signin_id = Card.id(cardish) || Card::AnonymousID
-
2112
self.current_id = signin_id
-
2112
set_session_user signin_id
-
end
-
-
# current user is not anonymous
-
# @return [true/false]
-
1
def signed_in?
-
507
current_id != Card::AnonymousID
-
end
-
-
# id of current user card.
-
# @return [Integer]
-
1
def current_id
-
47849
@current_id ||= Card::AnonymousID
-
end
-
-
# current accounted card (must have +\*account)
-
# @return [Card]
-
1
def current
-
462
if @current && @current.id == current_id
-
375
@current
-
else
-
87
@current = Card[current_id]
-
end
-
end
-
-
1
def current_roles
-
96
@current_roles ||= [Card.fetch_name(:anyone_signed_in),
-
current.fetch(:roles)&.item_names].flatten.compact
-
end
-
-
1
def serialize
-
188
{ as_id: as_id, current_id: current_id }
-
end
-
-
# @param auth_data [Integer|Hash] user id, user name, or a hash
-
# @option auth_data [Integer] current_id
-
# @option auth_data [Integer] as_id
-
1
def with auth_data
-
7
if auth_data.is_a?(Integer) || auth_data.is_a?(String)
-
auth_data = { current_id: Card.id(auth_data) }
-
end
-
-
7
tmp_current_id = current_id
-
7
tmp_as_id = as_id
-
7
tmp_current = @current
-
7
tmp_as_card = @as_card
-
7
tmp_current_roles = @current_roles
-
-
# resets @as and @as_card
-
7
self.current_id = auth_data[:current_id]
-
7
@as_id = auth_data[:as_id] if auth_data[:as_id]
-
7
yield
-
ensure
-
7
@current_id = tmp_current_id
-
7
@as_id = tmp_as_id
-
7
@current = tmp_current
-
7
@as_card = tmp_as_card
-
7
@current_roles = tmp_current_roles
-
end
-
-
# get session object from Env
-
# return [Session]
-
1
def session
-
2151
Card::Env.session
-
end
-
-
# set current from token, api_key, or session
-
1
def signin_with opts={}
-
39
if opts[:token]
-
signin_with_token opts[:token]
-
39
elsif opts[:api_key]
-
signin_with_api_key opts[:api_key]
-
else
-
39
signin_with_session
-
end
-
end
-
-
# set the current user based on token
-
1
def signin_with_token token
-
payload = Token.validate! token
-
signin payload[:anonymous] ? Card::AnonymousID : payload[:user_id]
-
end
-
-
# set the current user based on api_key
-
1
def signin_with_api_key api_key
-
1
account = find_account_by_api_key api_key
-
1
unless account&.validate_api_key! api_key
-
raise Card::Error::PermissionDenied, "API key authentication failed"
-
end
-
-
1
signin account.left_id
-
end
-
-
# get :user id from session and set Auth.current_id
-
1
def signin_with_session
-
39
card_id = session_user
-
39
signin(card_id && Card.exists?(card_id) ? card_id : nil)
-
end
-
-
# find +\*account card by +\*api card
-
# @param api_key [String]
-
# @return [+*account card, nil]
-
1
def find_account_by_api_key api_key
-
1
find_account_by :api_key, api_key.strip
-
end
-
-
# find +\*account card by +\*email card
-
# @param email [String]
-
# @return [+*account card, nil]
-
1
def find_account_by_email email
-
35
find_account_by :email, email.strip.downcase
-
end
-
-
# general pattern for finding +\*account card based on field cards
-
# @param fieldcode [Symbol] code of account field
-
# @param value [String] content of field
-
# @return [+*account card, nil]
-
1
def find_account_by fieldcode, value
-
36
Auth.as_bot do
-
36
Card.search({ right_id: Card::AccountID,
-
right_plus: [Card::Codename.id(fieldcode), { content: value }] },
-
"find +:account with +#{fieldcode} (#{value})").first
-
end
-
end
-
-
1
def session_user
-
39
session[session_user_key]
-
end
-
-
1
def set_session_user card_id
-
2112
session[session_user_key] = card_id
-
end
-
-
1
def session_user_key
-
2207
"user_#{database.underscore}".to_sym
-
end
-
-
1
def database
-
2207
Rails.configuration.database_configuration.dig Rails.env, "database"
-
end
-
-
# set the id of the current user.
-
1
def current_id= card_id
-
2132
@current = @as_id = @as_card = @current_roles = nil
-
2132
card_id = card_id.to_i if card_id.present?
-
2132
@current_id = card_id
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Auth
-
# singleton permission methods
-
1
module Permissions
-
# user has "root" permissions
-
# @return [true/false]
-
1
def always_ok?
-
18917
usr_id = as_id
-
18917
case usr_id
-
7270
when Card::WagnBotID then true # cannot disable
-
when nil then false
-
else
-
11647
always_ok_usr_id? usr_id
-
end
-
end
-
-
# specified user has root permission
-
# @param usr_id [Integer]
-
# @return [true/false]
-
1
def always_ok_usr_id? usr_id, force_cache_update=false
-
11647
always = always_cache
-
11647
if always[usr_id].nil? || force_cache_update
-
963
update_always_cache usr_id, admin?(usr_id)
-
else
-
10684
always[usr_id]
-
end
-
end
-
-
1
def update_always_cache usr_id, value
-
977
always = always_cache
-
977
always = always.dup if always.frozen?
-
977
always[usr_id] = value
-
977
Card.cache.write "ALWAYS", always
-
977
value
-
end
-
-
1
def always_cache
-
12624
Card.cache.read("ALWAYS") || {}
-
end
-
-
# list of names of cardtype cards that current user has perms to create
-
# @return [Array of strings]
-
1
def createable_types
-
type_names =
-
80
Auth.as_bot do
-
80
Card.search(
-
{ type: Card::CardtypeID, return: :name,
-
not: { codename: ["in"] + Card.config.non_createable_types } },
-
"find createable types"
-
)
-
end
-
-
80
type_names.select do |name|
-
3520
Card.new(type: name).ok? :create
-
end.sort
-
end
-
-
# test whether user is an administrator
-
# @param user_id [Integer]
-
# @return [true/false]
-
1
def admin? user_id
-
963
has_role? user_id, Card::AdministratorID
-
end
-
-
1
def has_role? user_id, role_id
-
963
return false unless user_id && role_id
-
-
963
Card[user_id].all_enabled_roles.include? role_id
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Auth
-
# mechanism for assuming permissions of another user.
-
1
module Proxy
-
# operate with the permissions of another "proxy" user
-
1
def as given_user
-
5828
tmp_id = @as_id
-
5828
tmp_card = @as_card
-
-
5828
@as_id = get_user_id(given_user)
-
5828
@as_card = nil
-
# we could go ahead and set as_card if given a card...
-
-
5828
@current_id = @as_id if @current_id.nil?
-
-
5828
return unless block_given?
-
-
5823
yield
-
ensure
-
5828
if block_given?
-
5823
@as_id = tmp_id
-
5823
@as_card = tmp_card
-
end
-
end
-
-
# operate with the permissions of WagnBot (administrator)
-
1
def as_bot &block
-
5235
as Card::WagnBotID, &block
-
end
-
-
# id of proxy user
-
# @return [Integer]
-
1
def as_id
-
51548
@as_id || current_id
-
end
-
-
# proxy user card
-
# @return [Card]
-
1
def as_card
-
11627
if @as_card && @as_card.id == as_id
-
10519
@as_card
-
else
-
1108
@as_card = Card[as_id]
-
end
-
end
-
-
# get card id from args of unknown type
-
# @todo replace with general mechanism, eg #quick_fetch
-
1
def get_user_id user
-
5828
case user
-
when NilClass then nil
-
487
when Card then user.id
-
5305
when Integer then user
-
36
else Card.fetch_id(user)
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Auth
-
# singleton methods for managing setup state
-
1
module Setup
-
1
NEEDS_SETUP = "NEEDS_SETUP".freeze
-
-
# app is not totally set up yet
-
# @return [true/false]
-
1
def needs_setup?
-
9
if @needs_setup == false || Card.cache.read(NEEDS_SETUP)&.to_s == "false"
-
@needs_setup = false
-
else
-
9
needs_setup_if_no_accounts
-
end
-
end
-
-
# for testing setup
-
1
def simulate_setup! mode=true
-
Card.cache.delete NEEDS_SETUP
-
@needs_setup = nil
-
@hidden_accounts = mode ? user_account_ids : nil
-
end
-
-
1
def instant_account_activation
-
simulate_needs_setup!
-
yield
-
ensure
-
simulate_needs_setup! false
-
end
-
-
1
private
-
-
1
def needs_setup_if_no_accounts
-
9
user_account_count.zero?.tap do |need|
-
9
Card.cache.write NEEDS_SETUP, false unless need
-
end
-
end
-
-
1
def user_account_ids
-
as_bot { Card.search user_account_cql.merge(return: :id) }
-
end
-
-
1
def user_account_cql
-
# every deck starts with two accounts: WagnBot and Anonymous
-
9
{ right_id: Card::AccountID, creator_id: ["ne", Card::WagnBotID] }
-
end
-
-
1
def user_account_count
-
9
cql = user_account_cql
-
9
cql[:not] = { id: ["in"].concat(@hidden_accounts) } if @hidden_accounts
-
18
as_bot { Card.count_by_cql cql }
-
end
-
end
-
end
-
end
-
1
require "jwt"
-
-
1
class Card
-
1
module Auth
-
# methods for setting current account
-
1
module Token
-
1
SECRET_KEY = Rails.application.secrets.secret_key_base.to_s
-
-
1
class << self
-
1
def encode user_id, extra_payload={}
-
45
payload = { user_id: user_id, exp: expiration }.merge(extra_payload)
-
-
45
JWT.encode payload, SECRET_KEY
-
end
-
-
# returns Hash if valid, String error message if not
-
-
1
def validate! token
-
payload = decode token
-
raise Card::Error::PermissionDenied, payload if payload.is_a? String
-
-
payload
-
end
-
-
1
def decode token
-
8
decoded = JWT.decode(token, SECRET_KEY)[0]
-
4
HashWithIndifferentAccess.new decoded
-
rescue JWT::DecodeError => error
-
4
error.message
-
end
-
-
1
def expiration
-
45
Card.config.token_expiry.from_now.to_i
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
class Cache
-
# _Persistent_ (or _Hard_) caches closely mirror the database and are
-
# intended to be altered only upon database alterations.
-
#
-
# Unlike the database, the persistent cache stores records of records that
-
# have been requested but are missing or, in the case of some {Card cards},
-
# "virtual", meaning that they follow known patterns but do not exist in the
-
# database.
-
#
-
# Most persistent cache implementations cannot store objects with singleton
-
# classes, therefore {Card cards} generally must have set_modules
-
# re-included after retrieval from the persistent cache.
-
#
-
1
class Persistent
-
1
attr_accessor :prefix
-
-
1
class << self
-
# name of current database; used here to insure that different databases
-
# are cached separately
-
# TODO: find better home for this method
-
1
def database_name
-
10
@database_name ||= (cfg = Cardio.config) &&
-
1
(dbcfg = cfg.database_configuration) &&
-
dbcfg[Rails.env]["database"]
-
end
-
-
1
def stamp
-
24
@stamp ||= Cardio.cache.fetch(stamp_key) { new_stamp }
-
end
-
-
# stamp generator
-
1
def new_stamp
-
17
Time.now.to_i.to_s(36) + rand(999).to_s(36)
-
end
-
-
1
def stamp_key
-
1
"#{database_name}-stamp"
-
end
-
-
1
def renew
-
@stamp = nil
-
end
-
-
1
def reset
-
@stamp = new_stamp
-
Cardio.cache.write stamp_key, @stamp
-
end
-
end
-
-
# @param opts [Hash]
-
# @option opts [Rails::Cache] :store
-
# @option opts [ruby Class] :class, typically ActiveRecord descendant
-
# @option opts [String] :database
-
1
def initialize opts
-
11
@store = opts[:store]
-
11
@klass = opts[:class]
-
11
@class_key = @klass.to_s.to_name.key
-
11
@database = opts[:database] || self.class.database_name
-
end
-
-
# renew insures you're using the most current cache version by
-
# reaffirming the stamp and prefix
-
1
def renew
-
67
@stamp = nil
-
67
@prefix = nil
-
end
-
-
# reset effectively clears the cache by setting a new stamp. However
-
# unlike annihilate, it won't bother other apps using the same cache engine.
-
1
def reset
-
12
@stamp = self.class.new_stamp
-
12
@prefix = nil
-
12
Cardio.cache.write stamp_key, @stamp
-
end
-
-
# the nuclear option. can affect other applications sharing the same
-
# cache engine. keep in mind mutually assured destruction.
-
1
def annihilate
-
@store.clear
-
end
-
-
# the current time stamp. changing this value effectively resets
-
# the cache. Note that Cardio.cache is a simple Rails::Cache, not
-
# a Card::Cache object.
-
1
def stamp
-
16
@stamp ||= Cardio.cache.fetch(stamp_key) { self.class.new_stamp }
-
end
-
-
# key for looking up the current stamp
-
1
def stamp_key
-
23
"#{@database}-#{@class_key}-#{self.class.stamp}-stamp"
-
end
-
-
# prefix added to cache key to create a system-wide unique key
-
1
def prefix
-
21
@prefix ||= "#{@database}-#{@class_key}-#{stamp}:"
-
end
-
-
# returns prefix/key
-
# @param key [String]
-
# @return [String]
-
1
def full_key key
-
13
"#{prefix}/#{key}"
-
end
-
-
1
def read key
-
6
@store.read full_key(key)
-
end
-
-
# update an attribute of an object already in the cache
-
# @param key [String]
-
# @param attribute [String, Symbol]
-
1
def write_attribute key, attribute, value
-
return value unless @store
-
-
if (object = deep_read key)
-
object.instance_variable_set "@#{attribute}", value
-
write key, object
-
end
-
value
-
end
-
-
1
def deep_read key
-
local_cache = @store.send :local_cache
-
local_cache&.clear
-
read key
-
end
-
-
1
def read_attribute key, attribute
-
object = deep_read key
-
object.instance_variable_get "@#{attribute}"
-
end
-
-
1
def write key, value
-
5
@store.write full_key(key), value
-
end
-
-
1
def fetch key, &block
-
1
@store.fetch full_key(key), &block
-
end
-
-
1
def delete key
-
1
@store.delete full_key(key)
-
end
-
-
1
def exist? key
-
@store.exist? full_key(key)
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# Content objects support the parsing of content strings into arrays that
-
# contain semantically meaningful "chunks" like nests, links, urls, etc.
-
#
-
# Each chunk has an object whose class inherits from {Card::Content::Chunk::Abstract}
-
#
-
1
class Content < SimpleDelegator
-
1
extend Clean
-
1
extend Truncate
-
-
1
Chunk # trigger autoload
-
-
1
attr_reader :revision, :format, :chunks, :opts
-
-
# initialization parses String, detects chunks
-
# @param content [String]
-
# @param format_or_card [Card::Format or Card]
-
# @param opts [Hash]
-
# @option opts [Symbol] :chunk_list - name of registered list of chunk
-
# classes to be used in parsing
-
1
def initialize content, format_or_card, opts={}
-
4237
@format = resolve_format format_or_card
-
4237
opts ||= {}
-
4237
chunk_list = opts[:chunk_list] || @format.chunk_list
-
4237
@chunks = Parser.new(chunk_list, self).parse(content)
-
4237
super(@chunks.any? ? @chunks : content)
-
end
-
-
# Content must be associated with a Format object, which in turn must be
-
# associated with a Card
-
# @return [Card]
-
1
def card
-
5539
@format.card
-
end
-
-
# Find all chunks of a given type
-
# @param chunk_type [Chunk Class]
-
# @return [Array of Chunk instances]
-
1
def find_chunks chunk_type
-
6327
each_chunk.select { |chunk| chunk.is_a?(chunk_type) }
-
end
-
-
1
def has_chunk? chunk_type
-
each_chunk.any { |chunk| chunk.is_a?(chunk_type) }
-
end
-
-
# sends &block to #process_chunk on each Chunk object
-
1
def process_chunks &block
-
1286
return custom_process_chunks(&block) if block_given?
-
-
1220
each_chunk(&:process_chunk)
-
end
-
-
1
def custom_process_chunks
-
66
each_chunk do |chunk|
-
252
chunk.burn_after_reading yield(chunk)
-
end
-
end
-
-
1
def pieces
-
3
Array.wrap(__getobj__)
-
end
-
-
1
def each_chunk
-
7025
return enum_for(:each_chunk) unless block_given?
-
-
iterator =
-
4169
case __getobj__
-
when Hash then :each_value
-
2401
when Array then :each
-
1768
when String then return # no chunks
-
else
-
Rails.logger.warn "unrecognized type for #each_chunk: " \
-
" #{self.class} #{__getobj__.class}"
-
return
-
end
-
14681
send(iterator) { |item| yield item if item.is_a?(Chunk::Abstract) }
-
end
-
-
# convert content to String.
-
# the common cases here are that either
-
#
-
# - (a) content is already a String, or
-
# - (b) it's an Array that needs to be iterated over and converted into a
-
# a string by running to_s on each item.
-
1
def to_s
-
1346
case __getobj__
-
937
when Array then map(&:to_s) * ""
-
409
when String then __getobj__
-
when NilClass then "" # raise "Nil Card::Content"
-
else __getobj__.to_s
-
end
-
end
-
-
1
def inspect
-
"<#{__getobj__.class}:#{card}:#{self}>"
-
end
-
-
1
def without_nests
-
without_chunks Chunk::Nest do |content|
-
yield content
-
end
-
end
-
-
1
def without_references
-
22
without_chunks Chunk::Nest, Chunk::Link do |content|
-
22
yield content
-
end
-
end
-
-
1
def without_chunks *chunk_classes
-
22
chunk_classes = ::Set.new Array.wrap(chunk_classes)
-
22
stash = stash_chunks chunk_classes
-
22
processed = yield to_s
-
22
unstash_chunks processed, stash
-
end
-
-
1
private
-
-
1
def stash_chunks chunk_classes
-
22
chunks = []
-
22
each_chunk do |chunk|
-
21
next unless chunk_classes.include? chunk.class
-
-
21
chunk.burn_after_reading "{{#{chunks.size}}}"
-
21
chunks << chunk.text
-
end
-
22
chunks
-
end
-
-
1
def unstash_chunks content, stashed_chunks
-
22
Chunk::Nest.gsub content do |nest_content|
-
21
number?(nest_content) ? stashed_chunks[nest_content.to_i] : "{{#{nest_content}}}"
-
end
-
end
-
-
1
def resolve_format format_or_card
-
4237
if format_or_card.is_a?(Card)
-
2909
Format.new format_or_card, format: nil
-
else
-
1328
format_or_card
-
end
-
end
-
-
1
def number? str
-
21
true if Float(str)
-
rescue StandardError
-
false
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
require "uri/common"
-
-
1
class Card
-
1
class Content < SimpleDelegator
-
# A chunk is a pattern of text that can be protected
-
# and interrogated by a format. Each Chunk class has a
-
# +pattern+ that states what sort of text it matches.
-
# Chunks are initalized by passing in the result of a
-
# match by its pattern.
-
#
-
1
module Chunk
-
1
mattr_accessor :raw_list, :prefix_regexp_by_list,
-
:prefix_map_by_list, :prefix_map_by_chunkname
-
1
@@raw_list = {}
-
1
@@prefix_regexp_by_list = {}
-
1
@@prefix_map_by_chunkname = {}
-
1
@@prefix_map_by_list = Hash.new { |h, k| h[k] = {} }
-
-
1
class << self
-
1
def register_class klass, hash
-
9
klass.config = hash.merge class: klass
-
9
prefix_index = hash[:idx_char] || :default
-
# ^ this is gross and needs to be moved out.
-
-
9
klassname = klass.name.split("::").last.to_sym
-
9
prefix_map_by_chunkname[klassname] = { prefix_index => klass.config }
-
9
raw_list.each do |key, list|
-
54
next unless list.include? klassname
-
-
15
prefix_map_by_list[key].merge! prefix_map_by_chunkname[klassname]
-
end
-
end
-
-
1
def register_list key, list
-
6
raw_list[key] = list
-
6
prefix_map_by_list[key] =
-
list.each_with_object({}) do |chunkname, h|
-
15
next unless (p_map = prefix_map_by_chunkname[chunkname])
-
-
h.merge! p_map
-
end
-
end
-
-
1
def find_class_by_prefix prefix, chunk_list_key=:default
-
6332
validate_chunk_list_key chunk_list_key
-
-
6332
prefix_map = prefix_map_by_list[chunk_list_key]
-
6332
config = prefix_map[prefix[0, 1]] ||
-
prefix_map[prefix[-1, 1]] ||
-
prefix_map[:default]
-
# prefix identified by first character, last character, or default.
-
# a little ugly...
-
-
6332
config[:class]
-
end
-
-
1
def prefix_regexp chunk_list_key
-
4237
prefix_regexp_by_list[chunk_list_key] ||=
-
build_prefix_regexp chunk_list_key
-
end
-
-
1
def build_prefix_regexp chunk_list_key
-
5
validate_chunk_list_key chunk_list_key
-
-
prefix_res =
-
5
raw_list[chunk_list_key].map do |chunkname|
-
14
chunk_class = const_get chunkname
-
14
chunk_class.config[:prefix_re]
-
end
-
5
/(?:#{ prefix_res * '|' })/m
-
end
-
-
1
def validate_chunk_list_key chunk_list_key
-
6337
unless raw_list.key? chunk_list_key
-
raise ArgumentError, "invalid chunk list key: #{chunk_list_key}"
-
end
-
end
-
end
-
-
# not sure whether this is best place.
-
# Could really happen almost anywhere
-
# (even before chunk classes are loaded).
-
1
register_list :default, %i[
-
URI HostURI EmailURI EscapedLiteral Nest Link
-
]
-
1
register_list :references, %i[EscapedLiteral Nest Link]
-
1
register_list :nest_only, [:Nest]
-
1
register_list :query, [:QueryReference]
-
1
register_list :stub, [:ViewStub]
-
1
register_list :references_keep_escaping, %i[KeepEscapedLiteral Nest Link]
-
end
-
end
-
1
Card::Mod::Loader.load_chunks
-
end
-
1
class Card
-
1
class Content < SimpleDelegator
-
# A chunk is a pattern of text that can be protected
-
# and interrogated by a format. Each Chunk class has a
-
# +pattern+ that states what sort of text it matches.
-
# Chunks are initalized by passing in the result of a
-
# match by its pattern.
-
#
-
1
module Chunk
-
1
class Abstract
-
1
class_attribute :config
-
1
attr_reader :text, :process_chunk
-
-
1
class << self
-
# if the prefix regex matched check that chunk against the full regex
-
1
def full_match content, prefix=nil
-
6352
content.match full_re(prefix)
-
end
-
-
1
def full_re _prefix
-
6345
config[:full_re]
-
end
-
-
1
def context_ok? _content, _chunk_start
-
6092
true
-
end
-
end
-
-
1
def reference_code
-
1039
"I"
-
end
-
-
1
def initialize match, content
-
6320
match = self.class.full_match(match) if match.is_a? String
-
6320
@text = match[0]
-
6320
@processed = nil
-
6320
@content = content
-
6320
interpret match, content
-
end
-
-
1
def interpret _match_string, _content
-
Rails.logger.info "no #interpret method found for chunk class: " \
-
"#{self.class}"
-
end
-
-
1
def format
-
9735
@content.format
-
end
-
-
1
def card
-
5539
@content.card
-
end
-
-
1
def to_s
-
2834
result
-
end
-
-
1
def result
-
2834
burn_read || @process_chunk || @processed || @text
-
end
-
-
1
def burn_read
-
2872
return unless @burn_read
-
-
273
tmp = @burn_read
-
273
@burn_read = nil
-
273
tmp
-
end
-
-
# Temporarily overrides the processed nest content for single-use
-
# After using the nest's result
-
# (for example via `to_s`) the original result is restored
-
1
def burn_after_reading text
-
273
@burn_read = text
-
end
-
-
1
def inspect
-
"<##{self.class}##{self}>"
-
end
-
-
1
def as_json _options={}
-
38
burn_read || @process_chunk || @processed ||
-
"not rendered #{self.class}, #{card&.name}"
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Content
-
# tools for cleaning content, especially for restricing unwanted HTML
-
1
module Clean
-
1
allowed_tags = {}
-
%w[
-
1
br i b pre cite caption strong em ins sup sub del ol hr ul li p
-
div h1 h2 h3 h4 h5 h6 span table tr td th tbody thead tfoot
-
32
].each { |tag| allowed_tags[tag] = [] }
-
-
# allowed attributes
-
1
allowed_tags.merge!(
-
"a" => %w[href title target],
-
"img" => %w[src alt title],
-
"code" => ["lang"],
-
"blockquote" => ["cite"]
-
)
-
-
1
if Cardio.config.allow_inline_styles
-
1
allowed_tags["table"] += %w[cellpadding align border cellspacing data-mce-style]
-
1
allowed_tags["td"] += %w[scope data-mce-style]
-
1
allowed_tags["th"] += %w[scope data-mce-style]
-
end
-
-
1
allowed_tags.each_key do |k|
-
36
allowed_tags[k] << "class"
-
36
allowed_tags[k] << "style" if Cardio.config.allow_inline_styles
-
36
allowed_tags[k]
-
end
-
-
1
ALLOWED_TAGS = allowed_tags.freeze
-
-
1
ATTR_VALUE_RE = [/(?<=^')[^']+(?=')/, /(?<=^")[^"]+(?=")/, /\S+/].freeze
-
-
1
def clean! string, tags=ALLOWED_TAGS
-
2402
cleaned = clean_tags string, tags
-
2402
cleaned = clean_spaces cleaned if Cardio.config.space_last_in_multispace
-
2402
cleaned
-
end
-
-
1
private
-
-
## Method that cleans the String of HTML tags
-
## and attributes outside of the allowed list.
-
1
def clean_tags string, ok_tags
-
# $LAST_MATCH_INFO is nil if string is a SafeBuffer
-
2402
string.to_str.gsub(%r{<(/*)(\w+)([^>]*)>}) do |_raw|
-
477
clean_tag $LAST_MATCH_INFO, ok_tags
-
end.gsub(/<\!--.*?-->/, "")
-
end
-
-
1
def clean_spaces string
-
2402
string.gsub(/(?:^|\b) ((?: )+)/, '\1 ')
-
end
-
-
1
def clean_tag match, ok_tags
-
477
tag = match[2].downcase
-
477
return " " unless (ok_attrs = ok_tags[tag])
-
423
"<#{match[1]}#{html_attribs tag, match[3], ok_attrs}>"
-
end
-
-
1
def html_attribs tag, raw_attr, ok_attrs
-
423
ok_attrs.each_with_object([tag]) do |ok_attr, pcs|
-
863
q, rest_value = process_attribute ok_attr, raw_attr
-
863
pcs << "#{ok_attr}=#{q}#{rest_value}#{q}" unless rest_value.blank?
-
end * " "
-
end
-
-
1
def process_attribute attrib, all_attributes
-
863
return ['"', nil] unless all_attributes =~ /\b#{attrib}\s*=\s*(?=(.))/i
-
-
14
q = '"'
-
14
rest_value = $'
-
14
if (idx = %w[' "].index Regexp.last_match(1))
-
13
q = Regexp.last_match(1)
-
end
-
14
reg_exp = ATTR_VALUE_RE[idx || 2]
-
14
rest_value = process_attribute_match rest_value, reg_exp, attrib
-
14
[q, rest_value]
-
end
-
-
# NOTE allows classes beginning with "w-" (deprecated)
-
1
def process_attribute_match rest_value, reg_exp, attrib
-
14
return rest_value unless (match = rest_value.match reg_exp)
-
-
14
rest_value = match[0]
-
14
if attrib == "class"
-
22
rest_value.split(/\s+/).select { |s| s =~ /^w-/i }.join(" ")
-
else
-
6
rest_value
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
class Content
-
1
class Diff
-
1
class << self
-
1
def complete a, b, opts={}
-
13
Card::Content::Diff.new(a, b, opts).complete
-
end
-
-
1
def summary a, b, opts={}
-
8
Card::Content::Diff.new(a, b, opts).summary
-
end
-
-
1
def render_added_chunk text
-
53
"<ins class='diffins diff-added'>#{text}</ins>"
-
end
-
-
1
def render_deleted_chunk text, _count=true
-
38
"<del class='diffdel diff-deleted'>#{text}</del>"
-
end
-
end
-
-
1
attr_reader :result
-
1
delegate :summary, :complete, :summary_omits_content?, to: :result
-
-
# diff options
-
# :format => :html|:text|:pointer|:raw
-
# :html = maintain html structure, but compare only content
-
# :text = remove all html tags; compare plain text
-
# :pointer = remove all double square brackets
-
# :raw = escape html tags and compare everything
-
#
-
# summary: {length: <number> , joint: <string> }
-
1
def initialize old_version, new_version, opts={}
-
33
@result = Result.new opts[:summary]
-
33
return unless new_version
-
-
33
lcs_opts = lcs_opts_for_format opts[:diff_format]
-
33
LCS.new(lcs_opts).run(old_version, new_version, @result)
-
end
-
-
1
def red?
-
4
@result.dels_cnt > 0
-
end
-
-
1
def green?
-
4
@result.adds_cnt > 0
-
end
-
-
1
private
-
-
1
def lcs_opts_for_format diff_format
-
33
opts = {}
-
33
case diff_format
-
when :html
-
8
opts[:exclude] = /^</
-
when :text
-
6
opts[:reject] = /^</
-
12
opts[:postprocess] = proc { |word| word.gsub("\n", "<br>") }
-
when :pointer
-
3
opts[:preprocess] = proc { |word| word.gsub("[[", "").gsub("]]", "<br>") }
-
else # :raw
-
65
opts[:preprocess] = proc { |word| CGI.escapeHTML(word) }
-
end
-
33
opts
-
end
-
end
-
end
-
end
-
# require "card/content/diff/processor"
-
-
1
class Card
-
1
class Content
-
1
class Diff
-
# Use LCS algorithm to create a {Diff::Result}
-
1
class LCS
-
1
def initialize opts
-
# regex; remove matches completely from diff
-
33
@reject_pattern = opts[:reject]
-
# regex; put matches back to the result after diff
-
33
@exclude_pattern = opts[:exclude]
-
-
33
@preprocess = opts[:preprocess] # block; called with every word
-
33
@postprocess = opts[:postprocess] # block; called with complete diff
-
-
33
@splitters = %w(<[^>]+> \[\[[^\]]+\]\] \{\{[^}]+\}\} \s+)
-
33
@disjunction_pattern = /^\s/
-
end
-
-
1
def run old_text, new_text, result
-
33
@result = result
-
33
compare old_text, new_text
-
33
@result.complete = postprocess @result.complete
-
end
-
-
1
private
-
-
1
def compare old_text, new_text
-
33
if old_text
-
27
old_words, old_ex = separate_comparables_from_excludees old_text
-
27
new_words, new_ex = separate_comparables_from_excludees new_text
-
27
processor = Processor.new old_words, new_words, old_ex, new_ex
-
27
processor.run @result
-
else
-
6
list = split_and_preprocess(new_text)
-
6
list = list.reject { |word| word.match @exclude_pattern } if @exclude_pattern
-
# CAUTION: postproces and added_chunk changed order
-
# and no longer postprocess for summary
-
6
@result.write_added_chunk list.join
-
end
-
end
-
-
1
def separate_comparables_from_excludees text
-
# return two arrays, one with all words, one with pairs
-
# (index in word list, html_tag)
-
54
list = split_and_preprocess text
-
54
if @exclude_pattern
-
16
check_exclude_and_disjunction_pattern list
-
else
-
38
[list, []]
-
end
-
end
-
-
1
def check_exclude_and_disjunction_pattern list
-
16
list.each_with_index.each_with_object([[], []]) do |pair, res|
-
103
element, index = pair
-
103
if element.match? @disjunction_pattern
-
32
res[1] << { chunk_index: index, element: element, type: :disjunction }
-
71
elsif element.match? @exclude_pattern
-
24
res[1] << { chunk_index: index, element: element, type: :excludee }
-
else
-
47
res[0] << element
-
end
-
end
-
end
-
-
1
def split_and_preprocess text
-
60
splitted = split_to_list_of_words(text).select do |s|
-
213
!s.empty? && (!@reject_pattern || !s.match(@reject_pattern))
-
end
-
109
@preprocess ? splitted.map { |s| @preprocess.call(s) } : splitted
-
end
-
-
1
def split_to_list_of_words text
-
60
split_regex = /(#{@splitters.join '|'})/
-
60
text.split(split_regex)
-
end
-
-
1
def preprocess text
-
@preprocess ? @preprocess.call(text) : text
-
end
-
-
1
def postprocess text
-
33
@postprocess ? @postprocess.call(text) : text
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Content
-
1
class Diff
-
1
class LCS
-
# Compares two lists of chunks and generates a diff
-
1
class Processor
-
1
def initialize old_words, new_words, old_excludees, new_excludees
-
27
@adds = []
-
27
@dels = []
-
27
@words = { old: old_words, new: new_words }
-
@excludees =
-
27
ExcludeeIterator.old_and_new old_excludees, new_excludees
-
end
-
-
1
def run result
-
27
@result = result
-
27
prev_action = nil
-
27
::Diff::LCS.traverse_balanced(@words[:old], @words[:new]) do |word|
-
62
process_word word, prev_action
-
62
prev_action = word.action
-
end
-
27
write_all
-
27
@result
-
end
-
-
1
def process_word word, prev_action
-
62
prev_action ? interpret_action(prev_action, word.action) : write_excludees
-
62
process_element word.old_element, word.new_element, word.action
-
end
-
-
1
def interpret_action prev_actn, word_actn
-
35
handle_action?(word_actn, prev_actn) ? handle_action(word_actn) : write_all
-
end
-
-
1
def handle_action? word_action, prev_action
-
35
(prev_action == word_action) ||
-
18
(prev_action == "-" && word_action == "!") ||
-
18
(prev_action == "!" && word_action == "+")
-
end
-
-
1
def handle_action action
-
17
case action
-
when "-" then del_old_excludees
-
11
when "+" then add_new_excludees
-
when "!" then
-
2
del_old_excludees
-
2
add_new_excludees
-
else
-
4
write_excludees
-
end
-
end
-
-
1
def write_all
-
45
write_dels
-
45
write_adds
-
45
write_excludees
-
end
-
-
1
def write_unchanged text
-
19
@result.write_unchanged_chunk text
-
end
-
-
1
def write_dels
-
45
return if @dels.empty?
-
-
24
@result.write_deleted_chunk @dels.join
-
24
@dels = []
-
end
-
-
1
def write_adds
-
45
return if @adds.empty?
-
-
29
@result.write_added_chunk @adds.join
-
29
@adds = []
-
end
-
-
1
def write_excludees
-
182
while (ex = @excludees[:new].next)
-
30
@result.write_excluded_chunk ex[:element]
-
end
-
end
-
-
1
def del_old_excludees
-
2
@excludees[:old].scan_and_record(@dels) do |element|
-
write_dels
-
@result.write_excluded_chunk element
-
end
-
end
-
-
1
def add_new_excludees
-
13
@excludees[:new].scan_and_record(@adds) do |element|
-
write_adds
-
@result.complete << element
-
end
-
end
-
-
1
def process_element old_element, new_element, action
-
62
case action
-
1
when "-" then minus old_element
-
17
when "+" then plus new_element
-
when "!"
-
25
minus old_element
-
25
plus new_element
-
else
-
19
write_unchanged new_element
-
19
@excludees[:new].word_step
-
end
-
end
-
-
1
def plus new_element
-
42
@adds << new_element
-
42
@excludees[:new].word_step
-
end
-
-
1
def minus old_element
-
26
@dels << old_element
-
26
@excludees[:old].word_step
-
end
-
end
-
-
# support class for LCS::Processor
-
1
class ExcludeeIterator
-
1
def self.old_and_new old_excludees, new_excludees
-
{
-
27
old: new(old_excludees),
-
new: new(new_excludees)
-
}
-
end
-
-
1
def initialize list
-
54
@list = list
-
54
@index = 0
-
54
@chunk_index = 0
-
end
-
-
1
def word_step
-
87
@chunk_index += 1
-
end
-
-
1
def next
-
123
if @index < @list.size &&
-
@list[@index][:chunk_index] == @chunk_index
-
32
res = @list[@index]
-
32
@index += 1
-
32
@chunk_index += 1
-
32
res
-
end
-
end
-
-
1
def scan_and_record record_array
-
32
while (ex = self.next)
-
2
if ex[:type] == :disjunction
-
2
record_array << ex[:element]
-
else
-
yield ex[:element]
-
end
-
end
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Content
-
1
class Diff
-
# Result object for Diff processing
-
1
class Result
-
1
attr_accessor :complete, :summary, :dels_cnt, :adds_cnt
-
1
def initialize summary_opts=nil
-
33
@dels_cnt = 0
-
33
@adds_cnt = 0
-
33
@complete = ""
-
33
@summary = Summary.new summary_opts
-
end
-
-
1
def summary
-
13
@summary.rendered
-
end
-
-
1
def summary_omits_content?
-
5
@summary.omits_content?
-
end
-
-
1
def write_added_chunk text
-
35
@adds_cnt += 1
-
35
@complete << Card::Content::Diff.render_added_chunk(text)
-
35
@summary.add text
-
end
-
-
1
def write_deleted_chunk text
-
24
@dels_cnt += 1
-
24
@complete << Card::Content::Diff.render_deleted_chunk(text)
-
24
@summary.delete text
-
end
-
-
1
def write_unchanged_chunk text
-
19
@complete << text
-
19
@summary.omit
-
end
-
-
1
def write_excluded_chunk text
-
30
@complete << text
-
end
-
-
# Summary object for Diff processing
-
1
class Summary
-
1
def initialize opts
-
33
opts ||= {}
-
33
@remaining_chars = opts[:length] || 50
-
33
@joint = opts[:joint] || "..."
-
-
33
@summary = nil
-
33
@chunks = []
-
33
@content_omitted = false
-
end
-
-
1
def rendered
-
13
@summary ||=
-
begin
-
13
truncate_overlap
-
13
@chunks.map do |chunk|
-
30
@content_omitted ||= chunk[:action] == :ellipsis
-
30
render_chunk chunk[:action], chunk[:text]
-
end.join
-
end
-
end
-
-
1
def add text
-
35
add_chunk text, :added
-
end
-
-
1
def delete text
-
24
add_chunk text, :deleted
-
end
-
-
1
def omit
-
19
if @chunks.empty? || @chunks.last[:action] != :ellipsis
-
15
add_chunk @joint, :ellipsis
-
end
-
end
-
-
1
def omits_content?
-
5
@content_omitted || @remaining_chars < 0
-
end
-
-
1
private
-
-
1
def add_chunk text, action
-
74
if @remaining_chars > 0
-
71
@chunks << { action: action, text: text }
-
71
@remaining_chars -= text.size
-
end
-
end
-
-
1
def render_chunk action, text
-
30
case action
-
when "+", :added
-
14
Card::Content::Diff.render_added_chunk text
-
when "-", :deleted
-
11
Card::Content::Diff.render_deleted_chunk text
-
5
else text
-
end
-
end
-
-
1
def truncate_overlap
-
13
return unless @remaining_chars < 0
-
-
3
process_ellipsis
-
-
3
index = @chunks.size - 1
-
3
while @remaining_chars < @joint.size && index >= 0
-
3
overlap_size = @remaining_chars + @chunks[index][:text].size
-
3
break if process_overlap overlap_size, index
-
-
index -= 1
-
end
-
end
-
-
1
def process_ellipsis
-
3
return unless @chunks.last[:action] == :ellipsis
-
-
@chunks.pop
-
@content_omitted = true
-
@remaining_chars += @joint.size
-
end
-
-
1
def process_overlap overlap_size, index
-
3
if overlap_size == @joint.size
-
1
replace_with_joint index
-
1
true
-
2
elsif overlap_size > @joint.size
-
2
cut_with_joint index
-
2
true
-
else
-
@remaining_chars += @chunks[index][:text].size
-
@chunks.delete_at(index)
-
false
-
end
-
end
-
-
1
def cut_with_joint index
-
2
@chunks[index][:text] =
-
2
@chunks[index][:text][0..(@remaining_chars - @joint.size - 1)]
-
2
@chunks[index][:text] += @joint
-
end
-
-
1
def replace_with_joint index
-
1
@chunks.pop
-
1
if index - 1 >= 0
-
1
if @chunks[index - 1][:action] == :added
-
@chunks << { action: :ellipsis, text: @joint }
-
1
elsif @chunks[index - 1][:action] == :deleted
-
1
@chunks << { action: :added, text: @joint }
-
end
-
end
-
end
-
end
-
end
-
end
-
end
-
end
-
# require "card/content/chunk"
-
-
1
class Card
-
1
class Content
-
# The Content::Parser breaks content strings into an Array of "chunks",
-
# each of which may be an instance of a {Chunk} class or a simple String.
-
1
class Parser
-
# @param chunk_list [Symbol] name of registered list of chunk classes
-
# to be used in parsing
-
# @see Card::Chunk.register_list
-
# @param content_object [Card::Content]
-
1
def initialize chunk_list, content_object
-
4237
@content_object = content_object
-
4237
@chunk_list = chunk_list
-
end
-
-
# break content string into an array of chunk objects and strings
-
# @param content [String]
-
# @return [Array]
-
1
def parse content
-
4237
@content = content
-
4237
@chunks = []
-
4237
return @chunks unless content.is_a? String
-
-
4237
@position = @last_position = 0
-
4237
@interval_string = ""
-
4237
parse_chunks
-
4237
@chunks
-
end
-
-
1
private
-
-
1
def parse_chunks
-
4237
prefix_regexp = Chunk.prefix_regexp @chunk_list
-
4237
match_prefices prefix_regexp
-
4237
handle_remainder
-
end
-
-
1
def match_prefices prefix_regexp
-
4237
while match_prefix prefix_regexp
-
6331
@chunk_class = Chunk.find_class_by_prefix @prefix, @chunk_list
-
# get the chunk class from the prefix
-
6331
content_slice = @content[@position..-1]
-
6331
@match, @offset = @chunk_class.full_match content_slice, @prefix
-
# see whether the full chunk actually matches
-
# (as opposed to bogus prefix)
-
6331
if @match # we have a chunk match
-
6305
next if record_chunk
-
else # no match. look at the next character
-
26
@position += 1
-
end
-
32
@interval_string += @content[@chunk_start..@position - 1]
-
# moving beyond the alleged chunk.
-
# append failed string to "nonchunk" string
-
end
-
end
-
-
1
def match_prefix prefix_regexp
-
10568
prefix_match = @content[@position..-1].match(prefix_regexp)
-
10568
if prefix_match
-
6331
@prefix = prefix_match[0]
-
# prefix of matched chunk
-
6331
@chunk_start = prefix_match.begin(0) + @position
-
# content index of beginning of chunk
-
6331
if prefix_match.begin(0) > 0
-
# if matched chunk is not beginning of test string
-
5006
@interval_string += @content[@position..@chunk_start - 1]
-
# hold onto the non-chunk part of the string
-
end
-
6331
@position = @chunk_start
-
# move scanning position up to beginning of chunk
-
6331
true
-
end
-
end
-
-
1
def record_chunk
-
6305
@position += (@match.end(0) - @offset.to_i)
-
# move scanning position up to end of chunk
-
6305
if !@chunk_class.context_ok? @content, @chunk_start
-
# make sure there aren't contextual reasons for ignoring this chunk
-
6
false
-
else
-
6299
@chunks << @interval_string unless @interval_string.empty?
-
6299
@interval_string = ""
-
# add the nonchunk string to the chunk list and
-
# reset interval string for next go-round
-
6299
@chunks << @chunk_class.new(@match, @content_object)
-
# add the chunk to the chunk list
-
6299
@last_position = @position
-
# note that the end of the chunk was the last place where a
-
# chunk was found (so far)
-
6299
true
-
end
-
end
-
-
1
def handle_remainder
-
4237
if @chunks.any? && @last_position < @content.size
-
# handle any leftover nonchunk string at the end of content
-
1089
@chunks << @content[@last_position..-1]
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Content
-
# tools for truncating content
-
1
module Truncate
-
1
ELLIPSES_HTML = '<span class="closed-content-ellipses">...</span>'.freeze
-
-
1
def smart_truncate input, words=25
-
return if input.nil?
-
-
truncated, wordstring = truncate input, words
-
# nuke partial tags at end of snippet
-
wordstring.gsub!(/(<[^\>]+)$/, "")
-
wordstring = close_tags wordstring
-
wordstring += ELLIPSES_HTML if truncated
-
# wordstring += '...' if wordlist.length > l
-
polish wordstring
-
end
-
-
1
private
-
-
1
def truncate input, words
-
wordlist = input.to_s.split
-
l = words.to_i - 1
-
l = 0 if l.negative?
-
truncating = wordlist.length > l
-
wordstring = truncating ? wordlist[0..l].join(" ") : input.to_s
-
[truncating, wordstring]
-
end
-
-
1
def close_tags wordstring
-
tags = find_tags wordstring
-
tags.each { |t| wordstring += "</#{t}>" }
-
wordstring
-
end
-
-
1
def polish wordstring
-
wordstring.gsub! %r{<[/]?br[\s/]*>}, " "
-
# Also a hack -- get rid of <br>'s -- they make line view ugly.
-
wordstring.gsub! %r{<[/]?p[^>]*>}, " "
-
## Also a hack -- get rid of <br>'s -- they make line view ugly.
-
wordstring
-
end
-
-
1
def find_tags wordstring
-
tags = []
-
-
# match tags with or without self closing (ie. <foo />)
-
wordstring.scan(%r{\<([^\>\s/]+)[^\>]*?\>}).each do |t|
-
tags.unshift(t[0])
-
end
-
# match tags with self closing and mark them as closed
-
wordstring.scan(%r{\<([^\>\s/]+)[^\>]*?/\>}).each do |t|
-
next unless (x = tags.index(t[0]))
-
-
tags.slice!(x)
-
end
-
# match close tags
-
wordstring.scan(%r{\</([^\>\s/]+)[^\>]*?\>}).each do |t|
-
next unless (x = tags.rindex(t[0]))
-
-
tags.slice!(x)
-
end
-
tags
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Director
-
1
class SubdirectorArray < Array
-
1
def self.initialize_with_subcards parent
-
2846
dir_array = new(parent)
-
2846
parent.card.subcards.each_card do |subcard|
-
172
dir_array.add subcard
-
end
-
2846
dir_array
-
end
-
-
1
def initialize parent
-
2846
@parent = parent
-
2846
super()
-
end
-
-
1
def add card
-
2042
card = card.card if card.is_a? Director
-
2042
existing(card) || fetch_new(card)
-
end
-
-
1
alias_method :delete_director, :delete
-
-
1
def delete card
-
3
if card.is_a? Director
-
1
delete_director card
-
else
-
4
delete_if { |dir| dir.card == card }
-
end
-
end
-
-
1
private
-
-
1
def existing card
-
4035
find { |dir| dir.card == card }
-
end
-
-
1
def fetch_new card
-
1422
Director.fetch(card, @parent).tap do |dir|
-
1422
update dir, card unless dir.main?
-
end
-
end
-
-
1
def update dir, card
-
1422
dir.replace_card card if dir.card != card
-
1422
dir.parent = @parent
-
1422
self << dir
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Env
-
# Success objects
-
1
class Success
-
1
include Card::Env::Location
-
-
1
attr_accessor :redirect, :name, :name_context, :reload
-
1
attr_writer :params, :card
-
1
attr_reader :id
-
-
1
def initialize name_context=nil, success_args=nil
-
159
@name_context = name_context
-
159
@new_args = {}
-
159
@params = OpenStruct.new
-
159
self << normalize_success_args(success_args)
-
end
-
-
1
def in_context name_context
-
13
self.name_context = name_context
-
13
self
-
end
-
-
1
def normalize_success_args success_args
-
159
case success_args
-
when nil
-
146
self.mark = "_self"
-
146
{}
-
when ActionController::Parameters
-
success_args.to_unsafe_h
-
else
-
13
success_args
-
end
-
end
-
-
1
def << value
-
164
if value.is_a? Hash
-
154
apply value
-
else
-
10
self.target = value
-
end
-
end
-
-
1
def reload?
-
13
@reload.to_s == "true"
-
end
-
-
# TODO: refactor to use cardish
-
1
def mark= value
-
159
case value
-
4
when Integer then @id = value
-
153
when String then @name = value
-
2
when Card then @card = value
-
else
-
self.target = value
-
end
-
end
-
-
# @deprecated
-
1
def id= id
-
# for backwards compatibility use mark here.
-
# id was often used for the card name
-
4
self.mark = id
-
end
-
-
1
def type= type
-
@new_args[:type] = type
-
end
-
-
1
def type_id= type_id
-
@new_args[:type_id] = type_id.to_i
-
end
-
-
1
def content= content
-
@new_args[:content] = content
-
end
-
-
1
def target= value
-
66
@id = @name = @card = nil
-
66
@target = process_target value
-
end
-
-
1
def process_target value
-
72
case value
-
2
when "" then ""
-
57
when "*previous", :previous then :previous
-
2
when %r{^(http|/)} then value
-
when /^REDIRECT:\s*(.+)/
-
6
@redirect = true
-
6
process_target Regexp.last_match(1)
-
5
else self.mark = value
-
end
-
end
-
-
1
def apply hash
-
155
hash.each_pair do |key, value|
-
21
self[key] = value
-
end
-
end
-
-
1
def card name_context=@name_context
-
225
if @card
-
15
@card
-
210
elsif @id
-
3
Card.fetch @id
-
207
elsif @name
-
76
Card.fetch @name.to_name.absolute(name_context), new: @new_args
-
end
-
end
-
-
1
def target name_context=@name_context
-
225
card(name_context) ||
-
131
(@target == :previous ? Card::Env.previous_location : @target) ||
-
Card.fetch(name_context)
-
end
-
-
1
def []= key, value
-
25
if respond_to? "#{key}="
-
12
send "#{key}=", value
-
else
-
13
@params.send "#{key}=", value
-
end
-
end
-
-
1
def [] key
-
1
if respond_to? key.to_sym
-
send key.to_sym
-
else
-
1
@params.send key.to_sym
-
end
-
end
-
-
1
def flash message=nil
-
126
@params[:flash] ||= []
-
126
@params[:flash] << message if message
-
126
@params[:flash]
-
end
-
-
1
def params
-
16
@params.marshal_dump
-
end
-
-
1
def raw_params
-
@params
-
end
-
-
1
def to_url name_context=@name_context
-
11
case (target = target(name_context))
-
when Card
-
7
target.format.path params
-
else
-
4
target
-
end
-
end
-
-
1
def method_missing method, *args
-
4
case method
-
when /^(\w+)=$/
-
3
self[Regexp.last_match(1).to_sym] = args[0]
-
when /^(\w+)$/
-
1
self[Regexp.last_match(1).to_sym]
-
else
-
super
-
end
-
end
-
-
1
def session
-
Card::Env.session
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# exceptions and errors.
-
# (arguably most of these should be Card::Exception)
-
1
class Error < StandardError
-
1
cattr_accessor :current
-
1
class_attribute :status_code, :view
-
1
attr_writer :backtrace
-
-
1
self.view = :errors
-
1
self.status_code = 422
-
-
1
attr_accessor :card
-
-
1
def initialize message=nil
-
29
if message.is_a? Card
-
1
self.card = message
-
1
message = message_from_card
-
end
-
29
super message
-
end
-
-
1
def message_from_card
-
1
I18n.t :exception_for_card,
-
scope: %i[lib card error], cardname: card.name, message: card_message_text
-
end
-
-
1
def backtrace
-
184
@backtrace || super
-
end
-
-
1
def report
-
7
Rails.logger.info "exception = #{self.class}: #{message}"
-
7
Rails.logger.debug backtrace.join("\n")
-
end
-
-
1
def card_message_text
-
card.errors.first&.message
-
end
-
-
# error attributable to code (as opposed to card configuration)
-
1
class ServerError < Error
-
1
def self.view
-
debugger_on? ? :debug_server_error : :server_error
-
end
-
-
1
def self.status_code
-
# Errors with status code 900 are displayed as modal instead of inside
-
# the "card-notice" div``
-
debugger_on? ? 900 : 500
-
end
-
-
1
def self.debugger_on?
-
Card::Codename[:debugger] && Card[:debugger]&.content =~ /on/
-
end
-
-
1
def report
-
2
super
-
2
card&.notable_exception_raised
-
end
-
end
-
-
# error whose message can be shown to any user
-
1
class UserError < Error
-
1
cattr_accessor :user_error_classes
-
1
self.user_error_classes = [self,
-
ActionController::BadRequest,
-
ActionController::MissingFile,
-
ActiveRecord::RecordNotFound,
-
ActiveRecord::RecordInvalid]
-
end
-
-
# error in CQL query
-
1
class BadQuery < UserError
-
end
-
-
1
class BadAddress < UserError
-
1
self.status_code = 404
-
1
self.view = :bad_address
-
end
-
-
# card not found
-
1
class NotFound < UserError
-
1
self.status_code = 404
-
1
self.view = :not_found
-
end
-
-
1
class CodenameNotFound < NotFound
-
end
-
-
# two editors altering the same card at once
-
1
class EditConflict < UserError
-
1
self.status_code = 409
-
1
self.view = :conflict
-
end
-
-
# permission errors
-
1
class PermissionDenied < UserError
-
1
self.status_code = 403
-
1
self.view = :denial
-
-
1
def card_message_text
-
1
card.errors[:permission_denied]
-
end
-
end
-
-
# exception class for aborting card actions
-
1
class Abort < StandardError
-
1
attr_reader :status
-
-
1
def report
-
Rails.logger.debug "aborting: #{message}"
-
end
-
-
1
def initialize status, msg=""
-
99
@status = status
-
99
super msg
-
end
-
end
-
-
# associating views with exceptions
-
1
class << self
-
1
KEY_MAP = { permission_denied: PermissionDenied,
-
conflict: EditConflict }.freeze
-
-
1
def report exception, card
-
7
e = cardify_exception exception, card
-
7
self.current = e
-
7
e.report
-
7
e
-
end
-
-
1
def cardify_exception exception, card
-
card_exception =
-
7
if exception.is_a? Card::Error
-
2
exception
-
else
-
5
card_error_class(exception, card).new exception.message
-
end
-
7
card_exception.card ||= card
-
7
card_exception.backtrace ||= exception.backtrace
-
7
add_card_errors card, card_exception if card.errors.empty?
-
7
card_exception
-
end
-
-
1
def add_card_errors card, exception
-
4
label = exception.class.to_s.split("::").last
-
4
card.errors.add label, exception.message
-
end
-
-
1
def card_error_class exception, card
-
# "simple" error messages are visible to end users and are generally not
-
# treated as software bugs (though they may be "shark" bugs)
-
5
case exception
-
when ActiveRecord::RecordInvalid
-
3
invalid_card_error_class card
-
when ActiveRecord::RecordNotFound, ActionController::MissingFile
-
Card::Error::NotFound
-
else
-
2
Card::Error::ServerError
-
end
-
end
-
-
1
def invalid_card_error_class card
-
3
KEY_MAP.each do |key, klass|
-
5
return klass if card.errors.key? key
-
end
-
2
Card::Error
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Format
-
# processing nests
-
1
class Nest
-
1
include Fetch
-
-
1
attr_accessor :format, :card, :view, :view_opts, :format_opts
-
1
def initialize format, cardish, view_opts={}, format_opts={}
-
7930
@format = format
-
7930
@view_opts = view_opts
-
7930
@format_opts = format_opts.clone
-
7930
@override = @format_opts.delete(:override) != false
-
7930
@card ||= fetch_card cardish
-
# note: fetch_card can alter view and view_opts[:nest_name]
-
end
-
-
1
def prepare
-
7930
prepare_view_and_opts!
-
7930
subformat = prepare_subformat
-
7930
@view = subformat.modal_nest_view @view if @override
-
7930
yield subformat, view
-
end
-
-
1
private
-
-
1
def prepare_view_and_opts!
-
7930
view_opts[:nest_name] ||= card.name
-
7930
@view ||= prepare_view
-
# TODO: handle in closed / edit view definitions
-
7930
view_opts[:home_view] ||= %i[closed edit].member?(view) ? :open : view
-
end
-
-
1
def prepare_view
-
7929
view = view_opts[:view] || format.implicit_nest_view
-
# TODO: canonicalize view and modal_nest_view handling should be in Card::View,
-
# not here. (Make sure processing only happens on nests/root views)
-
7929
Card::View.normalize view
-
end
-
-
# @return [Format] subformat object
-
1
def prepare_subformat
-
7930
return format if reuse_format?
-
-
7926
sub = format.subformat card, format_opts
-
7926
sub.main! if view_opts[:main]
-
7926
sub
-
end
-
-
# sometimes we use the same format (rather than a new subformat)
-
# when nesting the same card. this reduces overhead and optimizes
-
# caching
-
1
def reuse_format?
-
7930
self_nest? && !nest_recursion_risk?
-
end
-
-
1
def self_nest?
-
7930
self_nest = view_opts[:nest_name] =~ /^_(self)?$/ &&
-
format.context_card == format.card
-
-
# self nest in focal format should add depth (to catch recursions) but
-
# remain focal
-
7930
format_opts[:focal] = true if self_nest && format.focal?
-
7930
self_nest
-
end
-
-
# don't reuse the format when there is a risk of recursion, because while nest
-
# recursion is caught, view recursion is not.
-
# TODO: catch view recursion and remove this. (Should be straightforward within voo)
-
1
def nest_recursion_risk?
-
24
content_view? || format.voo&.structure
-
end
-
-
1
def content_view?
-
# TODO: this should be specified in view definition
-
24
%i[
-
bar expanded_bar core content titled open closed open_content one_line_content
-
].member? @view.to_sym
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Format
-
1
class Nest
-
# Fetch card for a nest
-
1
module Fetch
-
1
private
-
-
1
def fetch_card cardish
-
7930
case cardish
-
5489
when Card then cardish
-
100
when Symbol, Integer then Card.fetch cardish
-
1015
when "_", "_self" then format.context_card
-
1326
else new_card cardish
-
end
-
rescue Card::Error::CodenameNotFound
-
1
not_found_codename cardish
-
end
-
-
1
def not_found_codename cardish
-
1
@view = :not_found
-
1
c = Card.new name: Array.wrap(cardish).join(Card::Name.joint).to_s
-
1
c.errors.add :codename, not_found_codename_error(cardish)
-
1
c
-
end
-
-
1
def not_found_codename_error codename
-
1
::I18n.t :exception_unknown_codename, codename: codename,
-
scope: "lib.card.codename"
-
end
-
-
1
def new_card cardish
-
1326
view_opts[:nest_name] = Card::Name[cardish].to_s
-
1326
Card.fetch cardish, new: new_card_args
-
end
-
-
1
def new_card_args
-
1326
args = { name: view_opts[:nest_name] }
-
1326
args[:type] = view_opts[:type] if view_opts[:type]
-
1326
args.merge(new_supercard_args)
-
.merge(new_main_args)
-
.merge(new_content_args)
-
end
-
-
1
def new_supercard_args
-
# special case. gets absolutized incorrectly. fix in name?
-
1326
return {} if view_opts[:nest_name].strip.blank?
-
1322
{ supercard: format.context_card }
-
end
-
-
1
def new_main_args
-
1326
nest_name = view_opts[:nest_name]
-
1326
return {} unless nest_name =~ /main/
-
31
{ name: nest_name.gsub(/^_main\+/, "+"),
-
supercard: format.root.card }
-
end
-
-
1
def new_content_args
-
1326
content = content_from_shorthand_param || content_from_subcard_params
-
1326
content ? { content: content } : {}
-
end
-
-
1
def content_from_shorthand_param
-
# FIXME: this is a lame shorthand; could be another card's key
-
# should be more robust and managed by Card::Name
-
1326
shorthand_param = view_opts[:nest_name].tr "+", "_"
-
1326
Env.params[shorthand_param]
-
end
-
-
1
def content_from_subcard_params
-
1326
Env.params.dig "subcards", view_opts[:nest_name], "content"
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
require "open-uri"
-
-
1
class Card
-
1
class Mailer < ActionMailer::Base
-
1
@@defaults = Card.config.email_defaults || {}
-
1
@@defaults.symbolize_keys!
-
1
@@defaults[:return_path] ||= @@defaults[:from] if @@defaults[:from]
-
1
@@defaults[:charset] ||= "utf-8"
-
1
default @@defaults
-
-
1
class << self
-
1
def new_mail *args, &block
-
102
mail = Mail.new(args, &block)
-
102
method = Card::Mailer.delivery_method
-
102
mail.delivery_method(method, Card::Mailer.send(:"#{method}_settings"))
-
102
mail.perform_deliveries = Card::Mailer.perform_deliveries
-
102
mail.raise_delivery_errors = Card::Mailer.raise_delivery_errors
-
102
mail
-
end
-
-
1
def layout message
-
103
<<-HTML
-
<!DOCTYPE html>
-
<html>
-
<head>
-
<meta http-equiv="Content-type" content="text/html;charset=UTF-8"/>
-
</head>
-
<body>
-
#{message}
-
</body>
-
</html>
-
HTML
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
class Migration < ActiveRecord::Migration[4.2]
-
1
include Card::Model::SaveHelper
-
1
@type = :deck_cards
-
-
1
class << self
-
# Rake tasks use class methods, migrations use instance methods.
-
# To avoid repetition a lot of instance methods here just call class
-
# methods.
-
# The subclass Card::CoreMigration needs a different @type so we can't use a
-
# class variable @@type. It has to be a class instance variable.
-
# Migrations are subclasses of Card::Migration or Card::CoreMigration
-
# but they don't inherit the @type. The method below solves this problem.
-
1
def type
-
7
@type || (ancestors[1]&.type)
-
end
-
-
1
def find_unused_name base_name
-
test_name = base_name
-
add = 1
-
while Card.exists?(test_name)
-
test_name = "#{base_name}#{add}"
-
add += 1
-
end
-
test_name
-
end
-
-
1
def migration_paths mig_type=type
-
7
Cardio.migration_paths mig_type
-
end
-
-
1
def schema mig_type=type
-
Cardio.schema mig_type
-
end
-
-
1
def schema_suffix mig_type=type
-
Cardio.schema_suffix mig_type
-
end
-
-
1
def schema_mode mig_type=type
-
Cardio.with_suffix mig_type do
-
paths = Cardio.migration_paths(type)
-
yield(paths)
-
end
-
end
-
-
1
def assume_migrated_upto_version
-
schema_mode do
-
ActiveRecord::Schema.assume_migrated_upto_version schema,
-
migration_paths
-
end
-
end
-
-
1
def data_path filename=nil
-
7
path = migration_paths.first
-
7
File.join([path, "data", filename].compact)
-
end
-
end
-
-
1
def contentedly
-
Card::Cache.reset_all
-
Cardio.schema_mode "" do
-
Card::Auth.as_bot do
-
yield
-
ensure
-
::Card::Cache.reset_all
-
end
-
end
-
end
-
-
# def disable_ddl_transaction #:nodoc:
-
# true
-
# end
-
-
1
def import_json filename, merge_opts={}
-
Card::Mailer.perform_deliveries = false
-
output_file = File.join data_path, "unmerged_#{filename}"
-
merge_opts[:output_file] ||= output_file
-
Card.merge_list read_json(filename), merge_opts
-
end
-
-
1
def import_cards filename, merge_opts={}
-
Card::Mailer.perform_deliveries = false
-
output_file = File.join data_path, "unmerged_#{filename}"
-
merge_opts[:output_file] ||= output_file
-
meta_data = JSON.parse(File.read(data_path(filename)))
-
full_data =
-
meta_data.map do |hash|
-
hash["content"] =
-
File.read data_path(File.join("cards", hash["name"].to_name.key))
-
hash
-
end
-
Card.merge_list full_data, merge_opts
-
end
-
-
# uses the data in cards.yml and the card content in db/migrate_cards/data/cards
-
# to update or create the cards given by name or key in names_or_keys
-
1
def merge_cards names_or_keys
-
names_or_keys = Array(names_or_keys)
-
Card::Mailer.perform_deliveries = false
-
-
Card::Migration::Import.new(data_path).merge only: names_or_keys
-
end
-
-
1
def merge_pristine_cards names_or_keys
-
names_or_keys = Array(names_or_keys)
-
-
pristine = names_or_keys.select { |n| !Card.exists?(n) || Card.fetch(n)&.pristine? }
-
merge_cards pristine
-
end
-
-
1
def read_json filename
-
raw_json = File.read data_path(filename)
-
json = JSON.parse raw_json
-
json.is_a?(Hash) ? json["card"]["value"] : json
-
end
-
-
1
def data_path filename=nil
-
self.class.data_path filename
-
end
-
-
1
def schema_mode
-
Cardio.schema_mode self.class.type
-
end
-
-
1
def migration_paths
-
Cardio.paths self.class.type
-
end
-
-
# Execute this migration in the named direction
-
# copied from ActiveRecord to wrap 'up' in 'contentendly'
-
1
def exec_migration conn, direction
-
@connection = conn
-
if respond_to?(:change)
-
if direction == :down
-
revert { change }
-
else
-
change
-
end
-
else
-
contentedly { send(direction) }
-
end
-
ensure
-
@connection = nil
-
end
-
-
1
def down
-
raise ActiveRecord::IrreversibleMigration
-
end
-
-
1
def update_machine_output
-
Card.search(right: { codename: "machine_output" }).each(&:delete)
-
end
-
end
-
end
-
-
1
require "card/migration/core"
-
# -*- encoding : utf-8 -*-
-
-
1
require "card/migration"
-
-
1
class Card
-
1
class Migration
-
1
class Core < Migration
-
1
@type = :core_cards
-
end
-
end
-
end
-
1
require_relative "import/import_data"
-
1
require_relative "import/merger"
-
-
1
class Card
-
1
class Migration
-
# Imports card data from a local or remote deck
-
#
-
# The cards' content for the import is stored for every card in a separate
-
# file, other attributes like name or type are stored for all cards together
-
# in a yml file.
-
#
-
# To update a card's content you only have to change the card's content
-
# file. The merge method will recognize that the file was changed
-
# since the last merge and merge it into the cards table
-
# To update other attributes change them in the yml file and either remove
-
# the 'merged' value or touch the corresponding content file
-
1
class Import
-
1
def initialize data_path
-
7
@data_path = data_path
-
end
-
-
# Merge the import data into the cards table.
-
# Bu default it merges only the data that was changed or added
-
# since the last merge.
-
# @param [Hash] opts choose which cards to merge
-
# @option opts [Boolean] :all merge all available import data
-
# @option opts [Array] :only a key/name or list of keys/names to
-
# be merged
-
1
def merge opts={}
-
1
Merger.new(@data_path, opts).merge
-
end
-
-
# Get import data from a deck
-
# @param [String] name The name of the card to be imported
-
# @param [Hash] opts pull options
-
# @option opts [String] remote Use a remote url. The remote url must
-
# have been registered via 'add_remote'
-
# @option opts [Boolean] deep if true fetch all nested cards, too
-
# @option opts [Boolean] items_only if true fetch all nested cards but
-
# not the card itself
-
1
def pull name, opts={}
-
6
update do |import_data|
-
6
url = opts[:remote] ? import_data.url(opts.delete(:remote)) : nil
-
6
fetch_card_data(name, url, opts).each do |card_data|
-
9
import_data.add_card card_data
-
end
-
end
-
end
-
-
# Add a card with the given attributes to the import data
-
1
def add_card attr
-
update do |data|
-
data.add_card attr
-
end
-
end
-
-
# Save an url as remote deck to make it available for the pull method
-
1
def add_remote name, url
-
1
update do |data|
-
1
data.add_remote name, url
-
end
-
end
-
-
1
private
-
-
1
def update &block
-
7
ImportData.update(@data_path, &block)
-
end
-
-
1
def importer
-
@importer ||= ImportData.new(@data_path)
-
end
-
-
# Returns an array of hashes with card attributes
-
1
def fetch_card_data name, url, opts
-
view, result_key =
-
6
if opts[:items_only]
-
["export_items", nil]
-
6
elsif opts[:deep]
-
3
["export", nil]
-
else
-
3
[nil, :card]
-
end
-
card_data =
-
6
if url
-
fetch_remote_data name, view, url
-
else
-
6
fetch_local_data name, view
-
end
-
6
result_key ? [card_data[result_key]] : card_data
-
end
-
-
1
def fetch_remote_data name, view, url
-
json_url = "#{url}/#{name}.json"
-
json_url += "?view=#{view}" if view
-
json = ::File.open(json_url).read
-
parse_and_symbolize json
-
end
-
-
1
def fetch_local_data name, view
-
6
Card::Auth.as_bot do
-
6
Card[name].format(format: :json).render!(view || :page)
-
end
-
end
-
-
1
def parse_and_symbolize json
-
parsed = JSON.parse(json)
-
case parsed
-
when Hash then
-
parsed.deep_symbolize_keys
-
when Array then
-
parsed.map(&:deep_symbolize_keys)
-
else
-
parsed
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Migration
-
1
class Import
-
# Handles the card attributes and remotes for the import
-
1
class ImportData
-
1
include CardContent
-
1
include CardAttributes
-
-
# Takes a block to update import data
-
# use #add_card and #add_remote in the block to make
-
# changes
-
1
def self.update data_path
-
8
data = ImportData.new(data_path)
-
8
yield(data)
-
8
data.write_attributes
-
end
-
-
1
def self.load data_path, opts={}
-
1
data = ImportData.new(data_path)
-
1
if opts[:all]
-
data.all_cards
-
1
elsif opts[:only]
-
data.select_cards opts[:only]
-
else
-
1
data.changed_cards
-
end
-
end
-
-
1
def initialize data_path
-
43
@path = File.join data_path, "cards.yml"
-
43
@card_content_dir = File.join data_path, "cards"
-
43
@data = read_attributes
-
end
-
-
1
def all_cards
-
cards.map { |data| prepare_for_import data }
-
end
-
-
1
def select_cards names_or_keys
-
names_or_keys.map do |key|
-
attributes = find_card_attributes(key)
-
unless attributes
-
raise("no entry for #{key} (key: #{key.to_name.key}) in #{@path}")
-
end
-
prepare_for_import attributes
-
end
-
end
-
-
1
def changed_cards
-
1
cards.map do |data|
-
1
next unless changed?(data)
-
-
1
prepare_for_import data
-
end.compact
-
end
-
-
# mark as merged
-
1
def merged data, time
-
1
update_attribute data["name"], :merged, time
-
end
-
-
# to be used in an update block
-
1
def add_card card_data
-
9
card_attr, card_content = split_attributes_and_content card_data
-
-
9
update_card_attributes card_attr
-
9
write_card_content card_attr, card_content
-
9
card_attr
-
end
-
-
# to be used in an update block
-
1
def add_remote name, url
-
1
remotes[name] = url
-
end
-
-
1
def url remote_name
-
remotes[remote_name.to_sym] || raise("unknown remote: #{remote_name}")
-
end
-
-
1
private
-
-
1
def split_attributes_and_content data
-
9
card_data = {}
-
9
%i[name type codename].each do |key|
-
27
card_data[key] = data[key] if data[key]
-
end
-
9
card_data[:key] = data[:name].to_name.key
-
9
[card_data, data[:content]]
-
end
-
-
1
def remotes
-
1
@data[:remotes]
-
end
-
-
1
def cards
-
20
@data[:cards]
-
end
-
-
1
def prepare_for_import data
-
1
hash = card_attributes(data)
-
1
hash[:content] = card_content(data)
-
1
%i[file image].each do |attach|
-
2
hash[attach] &&= card_attachment(attach, data)
-
end
-
1
hash.with_indifferent_access
-
end
-
-
1
def changed? data
-
1
!data[:merged] || content_changed?(data)
-
end
-
-
1
def card_attachment attach_type, data
-
Card::Migration.data_path "files/#{data[attach_type]}"
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Migration
-
1
class Import
-
1
class ImportData
-
# handles card attributes for import
-
1
module CardAttributes
-
1
def card_attributes data
-
1
card_attr = ::Set.new %i[name type codename file image]
-
4
data.select { |k, v| v && card_attr.include?(k) }
-
end
-
-
1
def update_card_attributes card_data
-
9
card_entry = find_card_attributes card_data[:name]
-
# we only want strings and not the whole name objects
-
# for name and type
-
9
card_data[:name] = card_data[:name].to_s
-
9
card_data[:type] = card_data[:type].to_s
-
9
if card_entry
-
card_entry.replace card_data
-
else
-
9
cards << card_data
-
end
-
end
-
-
1
def update_attribute name, attr_key, attr_value
-
1
card = find_card_attributes name
-
1
return unless card
-
-
card[attr_key] = attr_value
-
card
-
end
-
-
1
def write_attributes
-
8
File.write @path, @data.to_yaml
-
rescue SystemCallError
-
false
-
# card.yml not written
-
end
-
-
1
def read_attributes
-
43
ensure_path
-
43
return { cards: [], remotes: {} } unless File.exist? @path
-
-
23
YAML.load_file(@path).deep_symbolize_keys
-
end
-
-
1
def find_card_attributes name
-
10
key = name.to_name.key
-
10
cards.find do |attr|
-
5
key == (attr[:key].present? ? attr[:key] : attr[:name].to_name.key)
-
end
-
end
-
-
1
private
-
-
1
def ensure_path
-
43
dir = File.dirname(@path)
-
43
FileUtils.mkpath dir unless Dir.exist? dir
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Migration
-
1
class Import
-
1
class ImportData
-
# handles card content for import
-
1
module CardContent
-
1
def card_content data
-
1
File.read(content_path(data))
-
end
-
-
1
def content_changed? data
-
Time.parse(data[:merged]) < File.mtime(content_path(data))
-
end
-
-
1
private
-
-
1
def write_card_content data, content
-
9
FileUtils.mkpath @card_content_dir unless Dir.exist? @card_content_dir
-
9
File.write content_path(data), content.to_s
-
end
-
-
1
def content_path data
-
10
filename = (data[:key] || data[:name]).to_name.safe_key
-
10
File.join @card_content_dir, filename
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Migration
-
1
class Import
-
# executes the card import
-
1
class Merger
-
1
def initialize data_path, opts={}
-
1
@data_path = data_path
-
1
@output_path = File.join data_path, "unmerged"
-
1
@data = ImportData.load @data_path, opts
-
end
-
-
1
def merge
-
1
puts("nothing to merge") && return if @data.empty?
-
-
1
Card::Mailer.perform_deliveries = false
-
1
Card::Auth.as_bot do
-
1
Card.merge_list @data, output_file: @output_path
-
end
-
-
1
update_import_data
-
end
-
-
1
private
-
-
1
def update_import_data
-
1
update_time = Time.zone.now.to_s
-
1
ImportData.update(@data_path) do |import_data|
-
1
@data.each do |card_data|
-
1
import_data.merged card_data, update_time
-
end
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Mod
-
1
class LoadStrategy
-
# Put everything for the module definition in one string and the evaluate
-
# it immediately with ruby's eval method.
-
1
class Eval < LoadStrategy
-
1
def load_modules
-
2
each_file do |abs_path, module_names|
-
258
template = module_template.new module_names, abs_path, self
-
258
template.build
-
end
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# Card::Query is for finding implicit lists (or counts of lists) of cards.
-
#
-
# Search and Set cards use Card::Query to query the database, and it's also
-
# frequently used directly in code.
-
#
-
# Query "statements" (objects, really) are made in CQL (Card Query
-
# Language). Because CQL is used by Sharks, the primary language
-
# documentation is on decko.org. (https://decko.org/CQL_Syntax). Note that the
-
# examples there are in JSON, like Search card content, but statements in
-
# Card::Query are in ruby form.
-
#
-
# In Decko's current form, Card::Query generates and executes SQL statements.
-
# However, the SQL generation is largely (not yet fully) separated from the
-
# CQL statement interpretation.
-
#
-
# The most common way to use Card::Query is as follows:
-
# list_of_cards = Card::Query.run(statement)
-
#
-
# This is equivalent to:
-
# query = Card::Query.new(statement)
-
# list_of_cards = query.run
-
#
-
# Upon initiation, the query is interpreted, and the following key objects
-
# are populated:
-
#
-
# - @join - an Array of Card::Query::Join objects
-
# - @conditions - an Array of conditions
-
# - @mod - a Hash of other query-altering keys
-
# - @subqueries - a list of other queries nested within this one
-
#
-
# Each condition is either a SQL-ready string (boo) or an Array in this form:
-
# [ field_string_or_sym, Card::Value::Query object ]
-
1
module Query
-
1
require "card/query/clause"
-
1
require "card/query/card_query"
-
1
require "card/query/sql_statement"
-
# Card::Query::CardQuery
-
# After conversion, ATTRIBUTES is a Hash where the key is the attribute
-
# and the value is the attribute type:
-
# { id: :basic, name: :basic, key: :basic ...}
-
# This is used for rapid attribute type lookups in the interpretation phase.
-
ATTRIBUTES = {
-
# Each of the "basic" fields corresponds directly to a database field.
-
# their values are translated fairly directly into SQL-safe values.
-
# (These are referred to as "properties" in CQL documentation. Need to
-
# reconcile #EFM)
-
1
basic: %i[id name key type_id content left_id right_id
-
creator_id updater_id codename read_rule_id],
-
# "Relational" values can involve tying multiple queries together
-
relational: %i[type
-
part left right
-
editor_of edited_by last_editor_of last_edited_by
-
creator_of created_by
-
updater_of updated_by
-
link_to linked_to_by
-
include included_by
-
nest nested_by
-
-
refer_to referred_to_by
-
member_of member
-
-
found_by
-
not sort match name_match complete],
-
-
plus_relational: %i[plus left_plus right_plus],
-
conjunction: %i[and or all any],
-
ignore: %i[prepend append vars],
-
deprecated: %i[view params size]
-
}.each_with_object({}) do |pair, h|
-
58
pair[1].each { |v| h[v] = pair[0] }
-
end
-
-
1
CONJUNCTIONS = { any: :or, in: :or, or: :or, all: :and, and: :and }.freeze
-
-
1
MODIFIERS = %i[conj return sort sort_as group dir limit offset]
-
8
.each_with_object({}) { |v, h| h[v] = nil }
-
-
OPERATORS =
-
9
%w[!= = =~ < > in ~ is].each_with_object({}) { |v, h| h[v] = v }.merge(
-
{ eq: "=", gt: ">", lt: "<", match: "~", ne: "!=",
-
"not in": "not in", "is not": "is not", "!": "is not" }.stringify_keys
-
)
-
-
1
DEFAULT_ORDER_DIRS = { update: "desc", relevance: "desc" }.freeze
-
-
1
class << self
-
1
def new statement, comment=nil
-
4597
Query::CardQuery.new statement, comment
-
end
-
-
1
def run statement, comment=nil
-
4209
new(statement, comment).run
-
end
-
-
1
def class_for type
-
4007
const_get "#{type.capitalize}Query"
-
end
-
-
1
def safe_sql txt
-
5063
txt = txt.to_s
-
5063
raise "CQL contains disallowed characters: #{txt}" if txt.match?(/[^\w\s*().,]/)
-
-
5063
txt
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# superclass for CardQuery, ReferenceQuery, ActQuery, and ActionQuery
-
#
-
# Each of the Query classes handle interpretation of hash "statements"
-
# into a number of objects known to the SqlStatement class, including
-
# @conditions, @joins, @comment, and the catch-all @mods
-
#
-
# Sql queries involving multiple tables are made possible by the query
-
# hierarchy as tracked by subqueries (children) and superqueries (parents).
-
# For example, if one card links to another, then this can be represented
-
# as a CardQuery with a ReferenceQuery child that in turn has another
-
# CardQuery as its child.
-
#
-
# See AbstractQuery::Tie for more on how tables can be connected.
-
1
class AbstractQuery
-
1
include QueryHelper
-
1
include Tie
-
-
1
attr_reader :statement, :mods, :conditions, :vars,
-
:subqueries, :superquery, :comment, :negate
-
1
attr_accessor :joins, :conditions_on_join
-
-
1
def initialize statement, _comment=nil
-
8602
@subqueries = []
-
8602
@conditions = []
-
8602
@joins = []
-
8602
@mods = {}
-
-
8602
@statement = statement.clone
-
8602
init_instance_vars :context, :superquery, :fasten, :negate
-
8602
@vars = init_query_vars
-
8602
table_alias
-
end
-
-
1
def init_instance_vars *varnames
-
8602
varnames.each do |varname|
-
34408
instance_variable_set "@#{varname}", (@statement.delete(varname) || nil)
-
end
-
end
-
-
1
def init_query_vars
-
8602
if (v = @statement.delete :vars) then v.symbolize_keys
-
8599
elsif @superquery then @superquery.vars
-
4388
else {}
-
end
-
end
-
-
1
def interpret hash
-
2941
hash.each do |action, card|
-
2941
send action, card
-
end
-
end
-
-
1
def full?
-
140
false
-
end
-
-
1
def sql
-
4514
@sql ||= Query::SqlStatement.new(self).build.to_s
-
end
-
-
1
def root
-
28725
@root ||= @superquery ? @superquery.root : self
-
end
-
-
1
def root?
-
20677
root == self
-
end
-
-
1
def subquery opts={}
-
4209
klass = opts.delete(:class) || Query
-
4209
subquery = klass.new opts.merge(superquery: self)
-
4209
@subqueries << subquery
-
4209
subquery
-
end
-
-
1
def context
-
250
if !@context.nil?
-
233
@context
-
else
-
17
@context = superquery ? superquery.context : ""
-
end
-
end
-
-
1
def depth
-
8666
@depth ||= case
-
4384
when !superquery then 0
-
14
when fasten == :direct then superquery.depth
-
130
else superquery.depth + 1
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class AbstractQuery
-
# shared methods for queries
-
1
module QueryHelper
-
1
def direct_subqueries
-
8392
subqueries_with_fasten :direct
-
end
-
-
1
def subqueries_with_fasten fasten
-
8592
list = []
-
8592
subqueries.each do |s|
-
4206
next unless Array.wrap(fasten).include? s.fasten
-
-
200
list << s
-
200
list += s.subqueries_with_fasten s.fasten
-
end
-
8592
list
-
end
-
-
1
def table_alias
-
45917
@table_alias ||= begin
-
8602
if fasten == :direct
-
203
@superquery.table_alias
-
else
-
8399
"#{table_prefix}#{next_table_suffix}"
-
end
-
end
-
end
-
-
1
def next_table_suffix
-
12407
return root.next_table_suffix unless root?
-
-
8399
@table_suffix = (@table_suffix || -1) + 1
-
end
-
-
1
def fld field_name
-
5294
"#{table_alias}.#{field_name}"
-
end
-
-
1
def add_condition *args
-
10378
@conditions <<
-
10378
if args.size > 1
-
5192
[args.shift, Query::Value.new(args.shift, self)]
-
else
-
5186
args[0]
-
end
-
end
-
-
1
def current_conjunction
-
2939
"AND"
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class AbstractQuery
-
# The "Tie" methods support tying two queries (CardQuery, ReferenceQuery, etc)
-
# together. The "fasten" variable determines which tying strategy is used.
-
#
-
# We currently support three values for "fasten": :join, :exist, and :in
-
#
-
# In concept, here's how the different strategies would tie table A to table B
-
# in SQL assuming A.id = B.a_id
-
#
-
# - :join ... FROM A JOIN B ON A.id = B.a_id
-
# - :exist ... FROM A WHERE EXISTS (SELECT * FROM B WHERE A.id = B.a_id ...)
-
# - :in ... FROM A WHERE A.id IN (SELECT B.a_id FROM B WHERE ...)
-
#
-
# The different strategies will return the same values but the relative speed is
-
# context dependent.
-
1
module Tie
-
1
def tie subquery_type, val, fields={}, subquery_args={}
-
4005
subquery = tie_subquery subquery_type, subquery_args
-
4005
subquery.interpret val
-
4005
fields = { from: :id, to: :id }.merge fields
-
4005
fasten_tie subquery, fields
-
end
-
-
1
def tie_subquery subquery_type, subquery_args
-
4005
subquery_args[:class] = Query.class_for subquery_type
-
4005
subquery(subquery_args)
-
end
-
-
1
def fasten_tie subquery, fields={}
-
4005
method = "tie_with_#{subquery.fasten}"
-
4005
send method, subquery, fields
-
4005
subquery
-
end
-
-
1
def tie_with_join subquery, fields={}
-
3877
join = Join.new tie_with_join_args(subquery, fields)
-
3877
negate_join(subquery, join, fields) if subquery.negate
-
3877
joins << join
-
end
-
-
1
def tie_with_in subquery, fields
-
64
subquery.mods[:return] = fields[:to]
-
64
subquery.mods[:in_field] = fld(fields[:from])
-
end
-
-
1
def tie_with_exist subquery, fields
-
64
subquery.super_conditions fields if fields.present?
-
end
-
-
1
def fasten
-
25341
@fasten ||= root? ? :join : inherit_fasten
-
end
-
-
1
def tie_with_join_args subquery, fields
-
3877
args = { from: self, from_field: fields[:from],
-
to: subquery, to_field: fields[:to] }
-
3877
args[:side] = :left if left_join? subquery
-
3877
args
-
end
-
-
1
def left_join? subquery
-
3877
current_conjunction == "or" || subquery.negate
-
# reverse conjunction if negated?
-
end
-
-
1
def negate_join subquery, join, fields
-
88
subquery.conditions_on_join = join
-
88
add_condition "#{subquery.fld fields[:to]} is null"
-
end
-
-
1
def inherit_fasten
-
4067
superfasten = superquery.fasten
-
4067
superfasten == :direct ? superquery.inherit_fasten : superfasten
-
end
-
-
1
def super_conditions fields
-
64
superfield fields[:to], fields[:from]
-
end
-
-
1
def superfield myfield, superfield
-
64
add_condition "#{fld myfield} = #{superquery.fld superfield}"
-
end
-
-
1
def restrict id_field, val
-
1979
if (id = id_from_val(val))
-
1571
interpret id_field => id
-
else
-
408
tie :card, val, from: id_field
-
end
-
end
-
-
1
def id_from_val val
-
4482
case val
-
839
when Integer then val
-
3222
when String then Card.fetch_id(val) || -999
-
3
when Symbol then Card::Codename.id(val) || -999
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# support CQL queries that require the card_acts table
-
1
class ActQuery < AbstractQuery
-
1
def table
-
416
"card_acts"
-
end
-
-
1
def table_prefix
-
219
"cx"
-
end
-
-
1
def action_on card
-
189
tie :action, { action_on: card }, to: :card_act_id
-
end
-
-
1
def update_action_on card
-
12
tie :action, { update_action_on: card }, to: :card_act_id
-
end
-
-
1
def act_by card
-
18
tie :card, card, from: :actor_id
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# support CQL queries that require the card_acts table
-
1
class ActionQuery < AbstractQuery
-
1
def table
-
416
"card_actions"
-
end
-
-
1
def table_prefix
-
219
"cn"
-
end
-
-
1
def action_by card
-
18
tie :act, { act_by: card }, from: :card_act_id
-
end
-
-
1
def update_action_by card
-
6
add_update_condition
-
6
action_by card
-
end
-
-
1
def action_on card
-
201
tie :card, card, from: :card_id
-
end
-
-
1
def update_action_on card
-
12
add_update_condition
-
12
action_on card
-
end
-
-
1
def add_update_condition
-
18
add_condition "#{fld :action_type} = 1"
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# interpret CQL queries, transform them into SQL, and run them.
-
1
class CardQuery < AbstractQuery
-
1
include Clause
-
1
include Run
-
1
include MatchAttributes
-
1
include RelationalAttributes
-
1
include ReferenceAttributes
-
1
include FoundBy
-
1
include Interpretation
-
1
include Normalization
-
1
include Sorting
-
1
include Conjunctions
-
# Query Execution
-
-
# By default a query returns card objects. This is accomplished by returning
-
# a card identifier from SQL and then hooking into our caching system (see
-
# Card::Fetch)
-
-
1
def self.viewable_sql
-
3
Card::Query::SqlStatement.new.permission_conditions("cards")
-
end
-
-
1
def table
-
8929
"cards"
-
end
-
-
1
def table_prefix
-
5458
"c"
-
end
-
-
1
def initialize statement, comment=nil
-
5661
super statement
-
5661
@comment = comment || default_comment
-
5661
interpret @statement
-
end
-
-
1
def default_comment
-
1965
return if @superquery || !Card.config.sql_comments
-
-
695
statement.to_s
-
end
-
-
# Query Hierarchy
-
# @root, @subqueries, and @superquery are used to track a hierarchy of
-
# query objects. This nesting allows to find, for example, cards that
-
# link to cards that link to cards....
-
-
1
def limit
-
38
mods[:limit].to_i
-
end
-
-
1
def full?
-
8890
!superquery && mods[:return] != "count"
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# conjoining conditions
-
1
module Conjunctions
-
1
def all val
-
4
conjoin val, :and
-
end
-
1
alias_method :and, :all
-
-
1
def any val
-
173
conjoin val, :or
-
end
-
1
alias_method :or, :any
-
1
alias_method :in, :any
-
-
1
def not val
-
88
tie :card, val, { id: :id }, negate: true
-
end
-
-
1
def current_conjunction
-
6535
@mods[:conj].blank? ? :and : @mods[:conj]
-
end
-
-
1
private
-
-
1
def conjunction val
-
305
return unless [String, Symbol].member? val.class
-
-
28
CONJUNCTIONS[val.to_sym]
-
end
-
-
1
def conjoin val, conj
-
177
subquery = subquery fasten: :direct, conj: conj
-
177
conjoinable_val(val).each do |val_item|
-
344
subquery.interpret val_item
-
end
-
end
-
-
1
def conjoinable_val val
-
177
return val if val.is_a? Array
-
-
509
clause_to_hash(val).map { |key, value| { key => value } }
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# nest independent query
-
1
module FoundBy
-
1
def found_by val
-
29
found_by_cards(val).compact.each do |card|
-
29
subquery found_by_subquery(card)
-
end
-
end
-
-
1
private
-
-
1
def found_by_subquery card
-
29
found_by_statement(card).merge(fasten: :direct, context: card.name)
-
end
-
-
1
def found_by_statement card
-
29
card&.try(:cql_hash) || invalid_found_by_card!(card)
-
end
-
-
1
def invalid_found_by_card! card
-
3
raise Card::Error::BadQuery, '"found_by" value must be valid Search, ' \
-
"but #{card.name} is a #{card.type_name}"
-
end
-
-
1
def found_by_cards val
-
29
if val.is_a? Hash
-
Query.run val
-
else
-
29
fetch_found_by_cards val
-
end
-
end
-
-
1
def fetch_found_by_cards val
-
29
Array.wrap(val).map do |v|
-
29
Card.fetch v.to_name.absolute(context), new: {}
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# Interpret CQL. Once interpreted, SQL can be generated.
-
1
module Interpretation
-
1
INTERPRET_METHOD = { basic: :add_condition,
-
relational: :relate,
-
plus_relational: :relate_compound,
-
conjunction: :send }.freeze
-
-
# normalize and extract meaning from a clause
-
# @param clause [Hash, String, Integer] statement or chunk thereof
-
1
def interpret clause
-
8688
normalize_clause(clause).each do |key, val|
-
13961
interpret_item key, val
-
end
-
end
-
-
1
def interpret_item key, val
-
13961
if interpret_as_content? key
-
32
interpret content: [key, val]
-
13929
elsif interpret_as_modifier? key, val
-
3366
interpret_modifier key, val
-
else
-
10563
interpret_attributes key, val
-
end
-
end
-
-
1
def interpret_as_content? key
-
# eg "match" is both operator and attribute;
-
# interpret as attribute when "match" is key
-
13961
OPERATORS.key?(key.to_s) && !ATTRIBUTES[key]
-
end
-
-
1
def interpret_as_modifier? key, val
-
# eg when "sort" is hash, it can have subqueries
-
# and must be interpreted like an attribute
-
13929
MODIFIERS.key?(key) && !val.is_a?(Hash)
-
end
-
-
1
def interpret_modifier key, val
-
3366
@mods[key] = val.is_a?(Array) ? val : val.to_s
-
end
-
-
1
def interpret_attributes attribute, val
-
10563
attribute_type = ATTRIBUTES[attribute]
-
10563
if (method = INTERPRET_METHOD[attribute_type])
-
10556
send method, attribute, val
-
else
-
7
no_method_for_attribute_type attribute, attribute_type
-
end
-
end
-
-
1
def no_method_for_attribute_type attribute, type
-
7
return if type == :ignore
-
1
if type == :deprecated
-
1
deprecated_attribute attribute
-
else
-
bad_attribute! attribute
-
end
-
end
-
-
1
def deprecated_attribute attribute
-
1
Rails.logger.info "Card queries no longer support #{attribute} attribute"
-
end
-
-
1
def bad_attribute! attribute
-
raise Error::BadQuery, "Invalid attribute: #{attribute}"
-
end
-
-
1
def relate_compound key, val
-
has_multiple_values =
-
354
val.is_a?(Array) &&
-
291
(val.first.is_a?(Array) || conjunction(val.first).present?)
-
354
relate key, val, multiple: has_multiple_values
-
end
-
-
1
def relate key, val, opts={}
-
5350
multiple = opts[:multiple].nil? ? val.is_a?(Array) : opts[:multiple]
-
5350
method = opts[:method] || :send
-
5350
if multiple
-
9
relate_multi_value method, key, val
-
else
-
5341
send method, key, val
-
end
-
end
-
-
1
def relate_multi_value method, key, val
-
9
conj = conjunction(val.first) ? conjunction(val.shift) : :and
-
9
if conj == current_conjunction
-
# same conjunction as container, no need for subcondition
-
18
val.each { |v| send method, key, v }
-
else
-
9
send conj, (val.map { |v| { key => v } })
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# Implements the match attributes that match always against content and/or name.
-
# Currently that's different from the match operator that can be restricted to
-
# names or content.
-
# Example: { match: "name or content" } vs. { name: ["match", "a name"] }
-
# TODO: unify handling for both using full text indexing
-
1
module MatchAttributes
-
# match term anywhere in name or content
-
1
def match val
-
18
return unless val.present?
-
18
subconds = %i[name content].map do |field|
-
36
Value.new([:match, val], self).to_sql field
-
end
-
18
add_condition or_join(subconds)
-
end
-
-
# match names beginning with term
-
1
def complete val
-
2
val = val.to_name
-
2
if val.junction?
-
1
interpret left: val.left
-
1
interpret right: { complete: val.right } if val.right.present?
-
else
-
1
add_condition "#{table_alias}.key LIKE '#{val.to_name.key}%'"
-
end
-
end
-
-
# match term anywhere in name
-
# DEPRECATE - move handling to name: ["match", val]
-
1
def name_match val
-
1
interpret name: [:match, val]
-
end
-
-
1
private
-
-
1
def or_join conditions
-
18
"(#{Array(conditions).join ' OR '})"
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# normalize clause's keys and values.
-
1
module Normalization
-
1
def normalize_clause clause
-
8688
clause = clause_to_hash clause
-
8688
clause.symbolize_keys!
-
8688
clause.each do |key, val|
-
13967
next if key.to_sym == :return
-
# when return values are relative, they are relative to the name of the
-
# card returned, not the context card
-
12079
clause[key] = normalize_value val
-
end
-
8688
clause
-
end
-
-
1
def clause_to_hash clause
-
9194
case clause
-
8971
when Hash then clause
-
186
when Integer then { id: clause }
-
37
when String then { id: (Card::Lexicon.id(clause) || -2) }
-
when Symbol then { id: Card::Codename.id(clause) }
-
else raise Error::BadQuery, "Invalid clause: #{clause.inspect}"
-
end
-
end
-
-
1
def normalize_value val
-
13387
case val
-
8481
when Integer, Float, Hash, Symbol, NilClass then val
-
4465
when String then normalize_string_value val
-
441
when Array then normalize_array_value val
-
else raise Error::BadQuery, "Invalid value type: #{val.class} (#{val.inspect})"
-
end
-
end
-
-
1
def normalize_array_value val
-
1749
val.map { |v| normalize_value v }
-
end
-
-
1
def normalize_string_value val
-
4465
case val.to_s
-
when /^\$(\w+)$/
-
# replace from @vars when value starts with dollar sign
-
2
string_value_from_var Regexp.last_match[1]
-
when /\b_/
-
# absolutize based on @context when there are words beginning with "_"
-
208
val.to_name.absolute(context)
-
else
-
4255
val
-
end
-
end
-
-
1
def string_value_from_var varname
-
2
@vars[varname.to_sym].to_s.strip
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# interpret CQL attributes that involve references from one card to another
-
1
module ReferenceAttributes
-
1
def self.define_reference_method methodname, reftype, ref_method, ref_field
-
8
define_method methodname do |val|
-
2503
tie :reference,
-
{ ref_method => { reftype: reftype, card: val } },
-
to: ref_field
-
end
-
end
-
-
{
-
1
refer_to: %w[L I],
-
link_to: "L",
-
include: "I",
-
nest: "I"
-
}.each do |methodname, reftype|
-
4
define_reference_method methodname, reftype, :referee, :referer_id
-
end
-
-
{
-
1
referred_to_by: %w[L I],
-
linked_to_by: "L",
-
included_by: "I",
-
nested_by: "I"
-
}.each do |methodname, reftype|
-
4
define_reference_method methodname, reftype, :referer, :referee_id
-
end
-
-
# shortcut methods for role references
-
# DEPRECATE?
-
-
1
def member_of val
-
10
interpret right_plus: [Card::RolesID, refer_to: val]
-
end
-
-
1
def member val
-
3
interpret referred_to_by: { left: val, right: Card::RolesID }
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# interpret CQL attributes that relate multiple cards
-
# each method below corresponds to a relational CQL term
-
#
-
# NOTE: methods using "restrict" can be executed without
-
# tying in an additional query if the val in question can be
-
# reduced to an id.
-
1
module RelationalAttributes
-
1
def type val
-
312
restrict :type_id, val
-
end
-
-
1
def part val
-
137
right_val = val.is_a?(Integer) ? val : val.clone
-
137
any(left: val, right: right_val)
-
end
-
-
1
def left val
-
968
restrict :left_id, val
-
end
-
-
1
def right val
-
693
restrict :right_id, val
-
end
-
-
1
def editor_of val
-
189
tie_act :action_on, val
-
end
-
-
1
def updater_of val
-
12
tie_act :update_action_on, val
-
end
-
-
1
def edited_by val
-
12
tie_action :action_by, val
-
end
-
-
1
def updated_by val
-
6
tie_action :update_action_by, val
-
end
-
-
1
def last_editor_of val
-
3
tie :card, val, to: :updater_id
-
end
-
-
1
def last_edited_by val
-
3
restrict :updater_id, val
-
end
-
-
1
def creator_of val
-
3
tie :card, val, to: :creator_id
-
end
-
-
1
def created_by val
-
3
restrict :creator_id, val
-
end
-
-
# ~~~~~~ PLUS RELATIONAL
-
-
1
def left_plus val
-
23
junction val, :left, :right_id
-
end
-
-
1
def right_plus val
-
310
junction val, :right, :left_id
-
end
-
-
1
def plus val
-
23
any(left_plus: val, right_plus: val.deep_clone)
-
end
-
-
1
private
-
-
1
def tie_action action, val
-
18
tie :action, { action => val }, to: :card_id
-
end
-
-
1
def tie_act action, val
-
201
tie :act, { action => val }, to: :actor_id
-
end
-
-
1
def junction val, side, field
-
333
tie :card, junction_val(val, side), to: field
-
end
-
-
1
def junction_val val, side
-
333
part_clause, junction_clause = val.is_a?(Array) ? val : [val, {}]
-
333
clause_to_hash(junction_clause).merge side => part_clause
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# run CQL queries
-
1
module Run
-
# run the current query
-
# @return [Array] of card objects by default
-
1
def run
-
4380
retrn = statement[:return].present? ? statement[:return].to_s : "card"
-
4380
return_method = :"return_#{simple_result?(retrn) ? :simple : :list}"
-
4380
send return_method, run_sql, retrn
-
end
-
-
# @return [(not an Array)]
-
1
def return_simple sql_result, retrn
-
16773
send result_method(retrn), sql_result, retrn
-
end
-
-
# @return [Array]
-
1
def return_list sql_results, retrn
-
4355
large_list sql_results.length if sql_results.length > 1000
-
4355
sql_results.map do |record|
-
16748
return_simple record, retrn
-
end
-
end
-
-
1
def large_list length
-
Rails.logger.info "#{length} records returned by #{@statement}"
-
end
-
-
1
def result_method retrn
-
case
-
33540
when respond_to?(:"#{retrn}_result") then :"#{retrn}_result"
-
when (retrn =~ /id$/) then :id_result
-
6
when (retrn =~ /_\w+/) then :name_result
-
when (retrn == "key") then :key_result
-
else :default_result
-
end
-
end
-
-
1
def count_result results, _field
-
25
results.first["count"].to_i
-
end
-
-
1
def default_result record, field
-
record[field]
-
end
-
-
1
def id_result record, field
-
799
record[field].to_i
-
end
-
-
1
def raw_result record, _field
-
record
-
end
-
-
1
def key_result record, pattern=""
-
10
name_result(record, pattern).to_name.key
-
end
-
-
1
def name_result record, pattern=""
-
15366
name = record["name"]&.to_name
-
15366
name ||= Card::Lexicon.lex_to_name [record["left_id"], record["right_id"]]
-
15366
process_name name, pattern
-
end
-
-
1
def card_result record, _field
-
587
if alter_results?
-
4
Card.fetch name_result(record), new: {}
-
else
-
583
fetch_or_instantiate record
-
end
-
end
-
-
1
def fetch_or_instantiate record
-
583
card = Card.retrieve_from_cache_by_id record["id"]
-
583
unless card
-
239
card = Card.instantiate record
-
239
Card.write_to_cache card
-
end
-
583
card.include_set_modules
-
583
card
-
end
-
-
1
def run_sql
-
# puts "\nSQL = #{sql}"
-
4380
ActiveRecord::Base.connection.select_all sql
-
end
-
-
1
def process_name name, pattern=""
-
15366
name = pattern.to_name.absolute(name) if pattern =~ /_\w+/
-
15366
return name unless alter_results?
-
-
13
alter_result name
-
end
-
-
1
def alter_result name
-
13
name_parts = [statement[:prepend], name, statement[:append]].compact
-
13
Card::Name[name_parts]
-
end
-
-
1
def simple_result? retrn
-
4380
retrn == "count"
-
end
-
-
1
def alter_results?
-
15953
statement[:prepend] || statement[:append]
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class CardQuery
-
# handle relational (not simple) CQL sort values
-
#
-
# sorting with subqueries is not fully supported; only a few experimental
-
# examples have been attempted, and even for those the syntax is likely
-
# to change.
-
#
-
# Generally speaking, sorting subqueries will require a JOIN strategy (as
-
# opposed to the "WHERE EXISTS" strategy that is central to queries' main
-
# conditions.)
-
1
module Sorting
-
1
SORT_BY_ITEM_JOIN_MAP = { left: "left_id", right: "right_id" }.freeze
-
-
1
def sort val
-
2
return nil unless full?
-
-
2
sort_field = val[:return] || "db_content"
-
2
val = val.clone
-
2
item = val.delete(:item) || "left"
-
2
sort_by val, item, sort_field
-
end
-
-
1
def sort_by val, item, sort_field
-
2
if sort_field == "count"
-
1
sort_by_count val, item
-
else
-
1
sort_by_item_join val, item, sort_field
-
end
-
end
-
-
1
def sort_by_item_join val, item, sort_field
-
1
join_field = sort_by_item_join_field item
-
1
join = join_cards val, to_field: join_field,
-
side: "LEFT",
-
conditions_on_join: true
-
1
@mods[:sort] ||= "#{join.table_alias}.#{sort_field}"
-
end
-
-
1
def sort_by_item_join_field item
-
1
SORT_BY_ITEM_JOIN_MAP[item.to_sym] || sort_method_not_implemented(:join, item)
-
end
-
-
# EXPERIMENTAL!
-
# sort: { referred_to_by { right: "*follow" }, return count }
-
-
1
def sort_by_count val, item
-
1
method_name = "sort_by_count_#{item}"
-
1
sort_method_not_implemented :count, item unless respond_to? method_name
-
1
send method_name, val
-
end
-
-
1
def sort_method_not_implemented method, item
-
raise Card::Error::BadQuery, "sorting by ##{method}/#{item} not yet implemented"
-
end
-
-
1
def sort_by_count_referred_to val
-
1
@mods[:sort] = "coalesce(count,0)" # needed for postgres
-
1
sort_query = count_sort_query
-
1
sort_query.add_condition "referer_id in (#{count_subselect(val).sql})"
-
# FIXME: - SQL generated before SQL phase
-
-
1
sort_query.joins << Join.new(from: sort_query, side: "LEFT",
-
to: %w[card_references wr referee_id])
-
1
join_count_sort_query sort_query
-
end
-
-
1
def join_count_sort_query sort_query
-
1
sort_query.mods[:sort_join_field] =
-
"#{sort_query.table_alias}.id as sort_join_field"
-
# FIXME: HACK!
-
-
1
joins << Join.new(from: self, side: "LEFT",
-
to: [sort_query, "srtbl", "sort_join_field"])
-
end
-
-
1
def count_subselect val
-
1
Query.new val.merge(return: "id", superquery: self)
-
end
-
-
1
def count_sort_query
-
1
Query.new return: "coalesce(count(*), 0) as count",
-
group: "sort_join_field",
-
superquery: self
-
end
-
-
1
def join_cards val, opts={}
-
1
conditions_on_join = opts.delete :conditions_on_join
-
1
s = subquery
-
1
join_opts = { from: self, to: s }.merge opts
-
1
card_join = Join.new join_opts
-
1
joins << card_join unless opts[:from].is_a? Join
-
1
s.conditions_on_join = card_join if conditions_on_join
-
1
s.interpret val
-
1
s
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
module Clause
-
# attr_accessor :clause
-
-
1
def safe_sql text
-
5027
Query.safe_sql text
-
end
-
-
1
def quote v
-
5639
connection.quote(v)
-
end
-
-
1
def connection
-
5679
@connection ||= ActiveRecord::Base.connection
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# object representation of Card::Query joins
-
1
class Join
-
1
JOIN_OPT_KEYS = %i[side conditions
-
from from_table from_alias from_field
-
to to_table to_alias to_field].freeze
-
1
attr_accessor(*JOIN_OPT_KEYS)
-
-
# These two manage hierarchy of nested joins
-
1
attr_accessor :superjoin, :subjoins
-
-
# This example join clause:
-
#
-
# cards c LEFT JOIN card_actions ca on c.id = ca.card_id and ca.draft is null
-
#
-
# ...would translate into the following instance variables on the Join object:
-
#
-
# @side = "left"
-
# @from_table = "cards"
-
# @from_alias = "c"
-
# @from_field = "id"
-
# @to_table = "card_actions"
-
# @to_alias = "ca"
-
# @to_field = "card_id"
-
# @conditions = "ca.draft is null"
-
#
-
# all of the above can be set directly via opts using the keys with the same name.
-
#
-
# Join.new side: "left", from_table: "cards"...
-
#
-
# The from and to fields can also be set via :from and :to keys.
-
# (see #interpret_from_and_to)
-
#
-
# You can generally use Symbols in place of Strings where applicable.
-
#
-
1
def initialize opts={}
-
3880
interpret_from_and_to opts
-
3880
convert_opts_to_instance_variables opts
-
-
3880
@conditions = Array(@conditions).compact
-
3880
@subjoins = []
-
3880
register_superjoin
-
end
-
-
1
def side
-
7760
if !@side.nil?
-
248
@side.to_s.upcase
-
else
-
7512
@side = inside_or? ? "LEFT" : nil
-
end
-
end
-
-
1
def left?
-
3880
side == "LEFT"
-
end
-
-
1
private
-
-
1
def inside_or?
-
7512
from&.is_a?(Card::Query) && from.mods[:conj] == "or"
-
end
-
-
# the options :to and :from can be translated into the full table/alias/field trio.
-
#
-
# - An Array is interpreted in that order (table, alias, field)
-
# - A Hash expects the keys :table, :alias, and (optionally) :field
-
# - A table and alias can be inferred from Card::Query or Card::Query::Reference
-
# objects.
-
# - They can also be inferred from a Join object, but only as a :from value
-
#
-
# In all cases, if the field is not specified, it is assumed to be :id
-
1
def interpret_from_and_to opts
-
3880
%i[from to].each do |side|
-
7760
directional_hash_for_object(side, opts[side]).map do |key, value|
-
23280
opts[:"#{side}_#{key}"] ||= value
-
end
-
end
-
end
-
-
1
def directional_hash_for_object side, object
-
7760
case object
-
when nil then nil
-
when Hash then object
-
2
when Array then dir_hash(*object)
-
7758
when AbstractQuery then dir_hash_for_query object
-
when Join then dir_hash_for_join side, object
-
else dir_error(side, object)
-
end
-
end
-
-
1
def dir_hash table, table_alias, field=nil
-
7760
hash = { table: table, alias: table_alias }
-
7760
hash[:field] = field || :id
-
7760
hash
-
end
-
-
1
def dir_hash_for_query query
-
7758
dir_hash query.table, query.table_alias
-
end
-
-
1
def dir_hash_for_join side, object
-
raise "to: cannot be Join" if side == :to
-
-
dir_hash object.to_table, object.to_alias
-
end
-
-
1
def dir_error side, object
-
raise Card::Error::BadQuery, "invalid #{side} option: #{object}"
-
end
-
-
1
def convert_opts_to_instance_variables opts
-
3880
opts.each do |key, value|
-
31164
send "#{key}=", value if value.present? && JOIN_OPT_KEYS.member?(key)
-
end
-
end
-
-
1
def register_superjoin
-
3880
return unless @from.is_a? Join
-
-
@superjoin = @from
-
@superjoin.subjoins << self
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# support the use of the card_references table in CQL
-
1
class ReferenceQuery < AbstractQuery
-
1
def table
-
2511
"card_references"
-
end
-
-
1
def table_prefix
-
2503
"cr"
-
end
-
-
1
def referer hash
-
44
add_conditions :referer_id, hash
-
end
-
-
1
def referee hash
-
2459
add_conditions :referee_id, hash
-
end
-
-
1
def add_conditions outfield, hash
-
2503
add_reftype_condition hash[:reftype]
-
2503
add_outfield_condition outfield, hash[:card]
-
end
-
-
1
def add_outfield_condition outfield, outcard
-
2503
if outcard == "_none"
-
non_outfield
-
2503
elsif (id = id_from_val(outcard))
-
2493
outfield_id outfield, id
-
else
-
10
tie :card, outcard, from: outfield
-
end
-
end
-
-
1
def non_outfield
-
add_condition "#{fld :is_present} = 0"
-
end
-
-
1
def outfield_id outfield, id
-
2493
add_condition "#{fld(outfield)} = #{id}"
-
end
-
-
1
def add_reftype_condition reftype
-
2503
return unless reftype.present?
-
-
2503
reftype = Array.wrap reftype
-
2503
operator = (reftype.size == 1 ? "=" : "IN")
-
5190
quoted_letters = reftype.map { |letter| "'#{letter}'" } * ", "
-
2503
add_condition "#{fld(:ref_type)} #{operator} (#{quoted_letters})"
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# The SqlStatement class generates sql from the Query classes. However, the logic
-
# is not yet as cleanly separated as it should be.
-
-
# At present, SqlStatement contains (imho) too much knowledge about card constructs.
-
# For example, all the permission and trash handling is here.
-
#
-
# In principle, the Query class should "interpret" statements into a few objects and
-
# a clean Query hierarchy. The SqlStatement class should be able to traverse that
-
# hierarchy and do little more than run "to_sql" on its parts, and in so doing
-
# construct a valid SQL statement.
-
1
class SqlStatement
-
1
include Joins
-
1
include Where
-
1
include Order
-
-
1
def initialize query=nil
-
4517
@query = query
-
4517
@mods = query&.mods
-
end
-
-
1
def build
-
4514
@fields = fields
-
4514
@tables = tables
-
4514
@joins = joins
-
4514
@where = where
-
4514
@group = group
-
4514
@order = order
-
4514
@limit_and_offset = limit_and_offset
-
4514
self
-
end
-
-
1
def to_s
-
[
-
4514
comment, select, from, @joins, @where, @group, @order, @limit_and_offset
-
].compact.join " "
-
end
-
-
1
def select
-
4514
"#{leading_space}SELECT DISTINCT #{@fields}"
-
end
-
-
1
def from
-
4514
"FROM #{@tables}"
-
end
-
-
1
def leading_space
-
8522
" " * (@query.depth * 2)
-
end
-
-
1
def comment
-
4514
return nil unless Card.config.sql_comments && @query.comment
-
-
4384
"/* #{@query.comment} */\n"
-
end
-
-
1
def tables
-
4514
"#{@query.table} #{@query.table_alias}"
-
end
-
-
1
def fields
-
4514
table = @query.table_alias
-
4514
field = @mods[:return] unless @mods[:return] =~ /^_\w+/
-
4514
field = field.blank? ? :card : field.to_sym
-
4514
field = full_field(table, field)
-
4514
[field, @mods[:sort_join_field]].compact * ", "
-
end
-
-
1
def full_field table, field
-
4514
case field
-
2606
when :card, :raw then "#{table}.*"
-
when :content then "#{table}.db_content"
-
614
when :name, :key then "#{table}.name, #{table}.left_id, #{table}.right_id"
-
25
when :count then "coalesce(count( distinct #{table}.id),0) as count"
-
else
-
1269
standard_full_field table, field
-
end
-
end
-
-
1
def standard_full_field table, field
-
1269
if ATTRIBUTES[field.to_sym] == :basic
-
1239
"#{table}.#{field}"
-
else
-
30
safe_sql field
-
end
-
end
-
-
1
def group
-
4514
group = @mods[:group]
-
4514
"GROUP BY #{safe_sql group}" if group.present?
-
end
-
-
1
def limit_and_offset
-
4514
full_syntax do
-
4359
limit = @mods[:limit]
-
4359
offset = @mods[:offset]
-
4359
if limit.to_i.positive?
-
22
string = "LIMIT #{limit.to_i} "
-
22
string += "OFFSET #{offset.to_i} " if offset.present?
-
22
string
-
end
-
end
-
end
-
-
1
def full_syntax
-
9028
@query.full? ? yield : return
-
end
-
-
1
def safe_sql txt
-
36
Query.safe_sql txt
-
end
-
-
1
def cast_type type
-
1
cxn ||= ActiveRecord::Base.connection
-
1
(val = cxn.cast_types[type.to_sym]) ? val[:name] : safe_sql(type)
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class SqlStatement
-
# transform joins from Card::Query::Join objects to SQL string clause
-
1
module Joins
-
1
def joins query=nil
-
8392
query ||= @query
-
8392
joins_on_query(query).map do |join|
-
3880
join_clause join
-
end.flatten.join " "
-
end
-
-
1
def joins_on_query query
-
8392
query.direct_subqueries.unshift(query).map(&:joins).flatten
-
end
-
-
1
def join_clause join
-
3880
subclause = subjoins join
-
3880
table = join_table join
-
3880
on = on_clause join
-
3880
join_clause_parts(join, table, subclause, on).compact.join " "
-
end
-
-
1
def join_clause_parts join, table, subclause, on
-
3880
parts = ["\n#{leading_space}", join.side, "JOIN"]
-
3880
if join.left? && subclause.present?
-
11
parts + ["(#{table} #{subclause})", on]
-
else
-
3869
parts + [table, on, subclause]
-
end
-
end
-
-
1
def subjoins join
-
3880
return unless join.to.is_a? AbstractQuery
-
-
3878
joins join.to
-
end
-
-
1
def join_table join
-
3880
to_table = join.to_table
-
3880
to_table = "(#{to_table.sql})" if to_table.is_a? CardQuery
-
3880
[to_table, join.to_alias].join " "
-
end
-
-
1
def on_clause join
-
3880
on_conditions = join.conditions
-
3880
on_conditions.unshift ["#{join.from_alias}.#{join.from_field}",
-
"#{join.to_alias}.#{join.to_field}"].join(" = ")
-
3880
on_conditions += on_card_conditions(join) if join.to.is_a? CardQuery
-
3880
on_conditions.reject!(&:blank?)
-
3880
"ON #{basic_conditions(on_conditions) * ' AND '}"
-
end
-
-
1
def on_card_conditions join
-
1007
to = join.to
-
1007
explicit = to.conditions_on_join == join ? explicit_conditions(to) : nil
-
1007
[explicit, implicit_conditions(to)].compact
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# convert @query sort rep into order by statement
-
# order information is stored in @mods[:sort], @mods[:sort_as], and
-
# @mods[:dir]
-
1
class SqlStatement
-
ORDER_MAP = {
-
1
"id" => "id",
-
"update" => "updated_at",
-
"create" => "created_at",
-
"name" => "key",
-
"content" => "db_content",
-
"alpha" => "key", # DEPRECATED
-
"relevance" => "updated_at" # DEPRECATED
-
}.freeze
-
-
# build ORDER BY clause
-
1
module Order
-
1
def order
-
4514
full_syntax do
-
4359
"ORDER BY #{order_directives.join ', '}"
-
end
-
end
-
-
1
def order_directives
-
4359
Array.wrap(order_config).map do |order_key|
-
4359
order_directive order_key
-
end
-
end
-
-
1
def order_directive order_key
-
4359
field = order_field order_key
-
4359
@fields += ", #{field}"
-
4359
"#{field} #{order_dir order_key}"
-
end
-
-
1
def order_field order_key
-
4359
order_as do
-
4359
if (field = ORDER_MAP[order_key])
-
4357
"#{@query.table_alias}.#{field}"
-
else
-
2
safe_sql order_key
-
end
-
end
-
end
-
-
1
def order_as
-
4359
field = yield
-
4359
return field unless (as = @mods[:sort_as])
-
-
1
"CAST(#{field} AS #{cast_type(safe_sql(as))})"
-
end
-
-
1
def order_dir order_key
-
4359
if @mods[:dir].blank?
-
4357
DEFAULT_ORDER_DIRS[order_key.to_sym] || "asc"
-
else
-
2
safe_sql @mods[:dir]
-
end
-
end
-
-
1
def order_config
-
4359
@mods[:sort].blank? ? "update" : @mods[:sort]
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class SqlStatement
-
# handle where clause in SqlStatement
-
1
module Where
-
1
def where
-
4514
conditions = [explicit_conditions(@query), implicit_conditions(@query)]
-
4514
conditions = conditions.reject(&:blank?).join " AND "
-
4514
"WHERE #{conditions}" unless conditions.blank?
-
end
-
-
# conditions explicitly specified in the query object
-
1
def explicit_conditions query
-
8592
cond_list = basic_conditions query.conditions
-
8592
cond_list += conditions_from query.subqueries
-
8592
cond_list.reject!(&:blank?)
-
8592
format_conditions cond_list, query
-
end
-
-
# depending on how a query is "fastened", its conditions may be rendered
-
# along with the superquery's
-
1
def conditions_from subqueries
-
8592
subqueries.map do |query|
-
4206
next if query.conditions_on_join
-
-
4117
case query.fasten
-
64
when :exist then exist_condition query
-
64
when :in then in_condition query
-
3989
else explicit_conditions query
-
end
-
end
-
end
-
-
1
def exist_condition query
-
64
"#{maybe_not query}EXISTS (#{spaced_subquery_sql query})"
-
end
-
-
1
def maybe_not query
-
128
query.negate ? "NOT " : ""
-
end
-
-
1
def in_condition query
-
64
field = query.mods[:in_field]
-
64
"#{field} #{maybe_not query}IN (#{spaced_subquery_sql query})"
-
end
-
-
1
def spaced_subquery_sql subquery
-
128
"\n#{subquery.sql}\n#{leading_space}"
-
end
-
-
# the conditions stored in the query's @conditions variable
-
1
def basic_conditions conditions
-
12472
conditions.map do |condition|
-
15347
case condition
-
10162
when String then condition
-
5185
when Array then standard_condition(condition)
-
end
-
end
-
end
-
-
1
def standard_condition condition
-
5185
field, val = condition
-
5185
val.to_sql field
-
end
-
-
# handle trash and permissions
-
# only applies to card queries
-
1
def implicit_conditions query
-
5521
return unless query.is_a?(CardQuery)
-
-
5451
table = query.table_alias
-
5451
[trash_condition(table), permission_conditions(table)].compact * " AND "
-
end
-
-
1
def trash_condition table
-
5451
"#{table}.trash is false"
-
end
-
-
1
def permission_conditions table
-
5454
return if Auth.always_ok?
-
-
948
read_rules = Auth.as_card.read_rules
-
948
read_rule_list = read_rules.present? ? read_rules.join(",") : 1
-
948
"#{table}.read_rule_id IN (#{read_rule_list})"
-
end
-
-
# convert list of conditions to string
-
1
def format_conditions cond_list, query
-
8592
if cond_list.size > 1
-
5588
"(#{cond_list.join condition_joint(query)})"
-
else
-
3004
cond_list.join
-
end
-
end
-
-
1
def condition_joint query
-
5588
" #{query.current_conjunction.upcase} "
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
# handling for CQL value clauses, eg [operator, value]
-
1
class Value
-
1
include Clause
-
1
include MatchValue
-
-
1
SQL_FIELD = { name: "key", content: "db_content" }.freeze
-
-
1
attr_reader :query, :operator, :value
-
-
1
def initialize rawvalue, query
-
5228
@query = query
-
5228
@operator, @value = parse_value rawvalue
-
5228
canonicalize_operator
-
end
-
-
1
def to_sql field
-
5221
if @operator == "~"
-
40
match_sql field
-
else
-
5181
standard_sql field
-
end
-
end
-
-
1
private
-
-
1
def standard_sql field
-
5275
@value = Array.wrap(@value).map { |v| v.to_name.key } if field.to_sym == :name
-
5181
"#{field_sql field} #{@operator} #{sqlize @value}"
-
end
-
-
1
def parse_value value
-
5228
case value
-
175
when Array then parse_array_value value.clone
-
2
when nil then ["is", nil]
-
5051
else ["=", parse_simple_value(value)]
-
end
-
end
-
-
1
def parse_array_value array
-
175
operator = operator?(array.first) ? array.shift : :in
-
772
[operator, array.flatten.map { |i| parse_simple_value i }]
-
end
-
-
1
def parse_simple_value value
-
5648
case value
-
5645
when String, Integer then value
-
1
when Symbol then value.to_s
-
when nil then nil
-
else raise Error::BadQuery, "Invalid property value: #{value.inspect}"
-
end
-
end
-
-
1
def canonicalize_operator
-
5228
unless (target = OPERATORS[@operator.to_s])
-
raise Error::BadQuery, "Invalid operator: #{@operator}"
-
end
-
-
5228
@operator = target
-
end
-
-
1
def operator? key
-
175
OPERATORS.key? key.to_s
-
end
-
-
1
def sqlize v
-
5804
case v
-
when Query then v.to_sql
-
201
when Array then sqlize_array v
-
4
when nil then "NULL"
-
5599
else quote(v.to_s)
-
end
-
end
-
-
1
def sqlize_array array
-
201
array.flatten!
-
201
if array.size == 1 && !@operator.in?(["in", "not in"])
-
109
sqlize array.first
-
else
-
606
"(#{array.map { |x| sqlize(x) }.join(',')})"
-
end
-
end
-
-
1
def field_sql field
-
5181
"#{@query.table_alias}.#{standardize_field field}"
-
end
-
-
1
def standardize_field field
-
5200
SQL_FIELD[field.to_sym] || safe_sql(field.to_s)
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Query
-
1
class Value
-
1
class << self
-
1
def match_prefices
-
1
@match_prefices ||= %w[= ~]
-
end
-
-
1
def match_term_and_prefix_re
-
40
@match_term_and_prefix_re ||=
-
/^(?<prefix>[#{Regexp.escape match_prefices.join}]*)\s*(?<term>.*)$/
-
end
-
end
-
-
# handling for match operator
-
1
module MatchValue
-
1
def match_sql field
-
40
exact_name_match(field) ||
-
"#{match_field field} #{connection.match match_value}"
-
end
-
-
1
def exact_name_match field
-
40
return false unless match_prefix == "=" && field.to_sym == :name
-
"#{field_sql field} = #{quote match_term.to_name.key}"
-
end
-
-
1
def match_field field
-
40
fld = field.to_sym == :name ? "name" : standardize_field(field)
-
40
"#{@query.table_alias}.#{fld}"
-
end
-
-
1
def match_value
-
40
escape_regexp_characters unless match_prefix == "~~"
-
40
quote match_term
-
end
-
-
1
def match_term
-
78
@match_term || (parse_match_term_and_prefix && @match_term)
-
end
-
-
1
def match_prefix
-
80
@match_prefix || (parse_match_term_and_prefix && @match_prefix)
-
end
-
-
# if search val is prefixed with "~~", it is a MYSQL regexp
-
# (and will be passed through)
-
#
-
# Otherwise, all non-alphanumeric characters are escaped.
-
#
-
# A "~" prefix is ignored.
-
-
1
def parse_match_term_and_prefix
-
40
raw_term = Array.wrap(@value).join(" ")
-
40
matches = raw_term.match self.class.match_term_and_prefix_re
-
40
@match_prefix = matches[:prefix] || ""
-
40
@match_term = matches[:term] || ""
-
end
-
-
1
def escape_regexp_characters
-
38
match_term.gsub!(/(\W)/, '\\\\\1')
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# a Reference is a directional relationship from one card (the referer)
-
# to another (the referee).
-
1
class Reference < ApplicationRecord
-
1
class << self
-
# bulk insert improves performance considerably
-
# array takes form [ [referer_id, referee_id, referee_key, ref_type], ...]
-
1
def mass_insert array
-
1507
return if array.empty?
-
-
6373
value_statements = array.map { |values| "\n(#{values.join ', '})" }
-
sql = "INSERT into card_references "\
-
"(referer_id, referee_id, referee_key, ref_type) "\
-
1507
"VALUES #{value_statements.join ', '}"
-
1507
Card.connection.execute sql
-
end
-
-
# map existing reference to name to card via id
-
1
def map_referees referee_key, referee_id
-
2691
where(referee_key: referee_key).update_all referee_id: referee_id
-
end
-
-
# references no longer refer to card, so remove id
-
1
def unmap_referees referee_id
-
934
where(referee_id: referee_id).update_all referee_id: nil
-
end
-
-
# find all references to missing (eg deleted) cards and reset them
-
1
def unmap_if_referee_missing
-
1
joins(
-
"LEFT JOIN cards ON card_references.referee_id = cards.id"
-
).where(
-
"(cards.id IS NULL OR cards.trash IS TRUE) AND referee_id IS NOT NULL"
-
).update_all referee_id: nil
-
end
-
-
# remove all references from missing (eg deleted) cards
-
1
def delete_if_referer_missing
-
1
joins(
-
"LEFT JOIN cards ON card_references.referer_id = cards.id"
-
).where(
-
"cards.id IS NULL"
-
).pluck_in_batches(:id) do |group_ids|
-
# used to be .delete_all here, but that was failing on large dbs
-
Rails.logger.info "deleting batch of references"
-
where("id in (#{group_ids.join ','})").delete_all
-
end
-
end
-
-
# repair references one by one (delete, create, delete, create...)
-
# slower, but better than #recreate_all for use on running sites
-
1
def repair_all
-
delete_if_referer_missing
-
Card.where(trash: false).find_each do |card|
-
Rails.logger.info "updating references from #{card}"
-
card.include_set_modules
-
card.update_references_out
-
end
-
end
-
-
# delete all references, then recreate them one by one
-
# faster than #repair_all, but not recommended for use on running sites
-
1
def recreate_all
-
delete_all
-
Card.where(trash: false).find_each do |card|
-
Rails.logger.info "updating references from #{card}"
-
card.include_set_modules
-
card.create_references_out
-
end
-
end
-
end
-
-
# card that refers
-
1
def referer
-
Card[referer_id]
-
end
-
-
# card that is referred to
-
1
def referee
-
Card[referee_id]
-
end
-
end
-
end
-
1
unless defined? CARD_SEED_TABLES
-
CARD_SEED_TABLES =
-
1
%w[cards card_actions card_acts card_changes card_references
-
schema_migrations schema_migrations_core_cards
-
schema_migrations_deck schema_migrations_deck_cards].freeze
-
end
-
-
1
unless defined? CARD_SEED_PATH
-
1
CARD_SEED_PATH = File.join(
-
ENV["CARD_SEED_REPO_PATH"] || [Cardio.gem_root, "db", "seed"], "new"
-
)
-
end
-
-
1
unless defined? CARD_TEST_SEED_PATH
-
CARD_TEST_SEED_PATH = File.join(Cardio.gem_root, "db", "seed", "test", "fixtures")
-
end
-
-
1
unless defined? CARD_TEST_SEED_SCRIPT_PATH
-
1
CARD_TEST_SEED_SCRIPT_PATH = File.join(Cardio.gem_root, "db", "test_seed.rb")
-
end
-
1
class Card
-
1
module Set
-
1
class Type < Pattern::Base
-
1
def initialize card
-
4406
super
-
# support type inheritance
-
4406
@inherit_card = card unless module_key
-
end
-
-
1
def lookup_module_list modules_hash
-
6019
lookup_key = module_key || inherited_key
-
6019
modules_hash[lookup_key] if lookup_key
-
end
-
-
1
private
-
-
1
def inherited_key
-
238
if defined?(@inherited_key)
-
35
@inherited_key
-
else
-
203
@inherited_key = lookup_inherited_key
-
end
-
end
-
-
1
def lookup_inherited_key
-
203
return unless (card = @inherit_card)
-
-
203
@inherit_card = nil
-
203
return unless (type_code = default_type_code card)
-
-
203
mod_key = "Type::#{type_code.to_s.camelize}"
-
203
mod_key if mods_exist_for_key? mod_key
-
end
-
-
1
def default_type_code card
-
203
card.rule_card(:default)&.type_code
-
end
-
-
1
def mods_exist_for_key? mod_key
-
203
list_of_hashes = Card::Set.modules[:nonbase_format].values
-
203
list_of_hashes << Card::Set.modules[:nonbase]
-
406
list_of_hashes.any? { |h| h[mod_key] }
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
# API to create/update/delete additional cards together with the main card.
-
# The most common case is for fields but subcards don't have to be descendants.
-
#
-
# Subcards can be added as card objects or attribute hashes.
-
#
-
# Use the methods defined in core/set/all/subcards.rb
-
# Example
-
# Together with "my address" you want to create the subcards
-
# "my address+name", "my address+street", etc.
-
1
class Subcards
-
1
include Add
-
1
include Remove
-
1
include Relate
-
-
1
attr_accessor :context_card, :keys
-
1
def initialize context_card
-
2828
@context_card = context_card
-
2828
@keys = ::Set.new
-
end
-
-
1
def [] name
-
card(name) || field(name)
-
end
-
-
1
def field name
-
60
key = field_name_to_key name
-
60
fetch_subcard key if @keys.include? key
-
end
-
-
1
def card name
-
3
return unless @keys.include? name.to_name.key
-
-
3
fetch_subcard name
-
end
-
-
1
def present?
-
40
@keys.present?
-
end
-
-
1
def catch_up_to_stage stage_index
-
each_card do |subcard|
-
subcard.catch_up_to_stage stage_index
-
end
-
end
-
-
1
def rename old_name, new_name
-
201
return unless @keys.include? old_name.to_name.key
-
-
16
@keys.delete old_name.to_name.key
-
16
@keys << new_name.to_name.key
-
end
-
-
1
def respond_to_missing? method_name, _include_private=false
-
3
@keys.respond_to? method_name
-
end
-
-
1
def method_missing method, *args
-
3
return unless respond_to_missing?(method)
-
-
3
@keys.send method, *args
-
end
-
-
# fetch all cards first to avoid side effects
-
# e.g. deleting a user adds follow rules and +*account to subcards
-
# for deleting but deleting follow rules can remove +*account from the
-
# cache if it belongs to the rule cards
-
1
def cards
-
33174
@keys.map do |key|
-
10307
fetch_subcard key
-
end.compact
-
end
-
-
1
def each_card
-
33174
cards.each do |card|
-
10307
yield card
-
end
-
end
-
-
1
alias_method :each, :each_card
-
-
1
def each_with_key
-
2910
@keys.each do |key|
-
379
card = fetch_subcard(key)
-
379
yield(card, key) if card
-
end
-
end
-
-
1
def fetch_subcard key
-
10747
Card.fetch key, local_only: true, new: {}
-
end
-
-
1
private
-
-
1
def subcard_key cardish
-
1
key = case cardish
-
when Card then cardish.key
-
when Symbol then fetch_subcard(cardish).key
-
1
else cardish.to_name.key
-
end
-
1
key = absolutize_subcard_name(key).key unless @keys.include?(key)
-
1
key
-
end
-
-
1
def absolutize_subcard_name name
-
845
name = Card::Name[name]
-
845
return name if @context_card.name.parts.first.blank?
-
-
837
name.absolute_name @context_card.name
-
end
-
end
-
end
-
1
class Card
-
1
class Subcards
-
# Methods for adding subcards
-
1
module Add
-
# @example Add a subcard with name 'spoiler'
-
# add 'spoiler', type: 'Phrase', content: 'John Snow is a Targaryen'
-
# card_obj = Card.new name: 'spoiler', type: 'Phrase',
-
# content: 'John Snow is a Targaryen'
-
# add card_obj
-
# add name: 'spoiler', type: 'Phrase', content: 'John Snow is a Targaryen'
-
#
-
# @example Add a subcard that is added in the integration phase
-
# (and hence doesn't hold up the transaction for the main card)
-
# add 'spoiler', content: 'John Snow is a Targaryen'
-
# add card_obj, delayed: true
-
-
1
def << value
-
add value
-
end
-
-
1
def []= name, card_or_attr
-
case card_or_attr
-
when Hash
-
new_by_attributes name, card_or_attr
-
when Card
-
new_by_card card_or_attr
-
end
-
end
-
-
1
def add *args
-
2465
case args.first
-
984
when Card then new_by_card args.first
-
984
when Hash then add_hash args.first
-
497
else new_by_attributes(*args)
-
end
-
end
-
-
1
def add_hash hash
-
984
if (name = hash.delete :name)
-
2
new_by_attributes name, hash
-
else
-
982
multi_add hash
-
end
-
end
-
-
1
def add_child name, args
-
97
name = name.is_a?(Symbol) ? name.cardname : name.to_name
-
97
add name.prepend_joint, args
-
end
-
1
alias_method :add_field, :add_child
-
-
1
def new_by_card card
-
1829
card.supercard = @context_card
-
1829
if !card.name.simple? && card.name.field_of?(@context_card.name)
-
771
card.superleft = @context_card
-
end
-
1829
@keys << card.key
-
1829
Card.write_to_soft_cache card
-
1829
card.director = @context_card.director.subdirectors.add card
-
1829
card
-
end
-
-
1
def new_by_attributes name, attributes={}
-
845
attributes ||= {}
-
845
absolute_name = absolutize_subcard_name name
-
845
subcard_args = extract_subcard_args! attributes
-
845
card = initialize_by_attributes absolute_name, attributes
-
845
subcard = new_by_card card
-
845
card.subcards.add subcard_args
-
845
subcard
-
end
-
-
1
def initialize_by_attributes name, attributes
-
845
Card.assign_or_newish name, attributes, local_only: true
-
end
-
-
# TODO: this method already exists as card instance method in
-
# tracked_attributes.rb. Find a place for it where its accessible
-
# for both. There is one important difference. The keys are symbols
-
# here instead of strings
-
1
def extract_subcard_args! args
-
845
subcards = args.delete(:subcards) || {}
-
845
if (subfields = args.delete(:subfields))
-
1
subfields.each_pair do |key, value|
-
1
subcards[normalize_subfield_key(key)] = value
-
end
-
end
-
845
args.keys.each do |key|
-
518
subcards[key] = args.delete(key) if key =~ /^\+/
-
end
-
845
subcards
-
end
-
-
1
private
-
-
# ensure a leading '+'
-
1
def normalize_subfield_key key
-
1
key = Card::Codename.name(key) if key.is_a?(Symbol) && Card::Codename.exist?(key)
-
1
key.to_name.prepend_joint
-
end
-
-
# Handles hash with several subcards
-
1
def multi_add args
-
982
args.each_pair do |key, val|
-
346
case val
-
when String, Array, Integer
-
240
new_by_attributes key, content: val
-
when Card
-
val.name = absolutize_subcard_name key
-
new_by_card val
-
when nil
-
next
-
else
-
106
new_by_attributes key, val
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Subcards
-
# Methods for handling related subcards
-
1
module Relate
-
1
def field_name_to_key name
-
60
if @context_card.name.starts_with_joint?
-
relative_child(name).key
-
else
-
60
child(name).key
-
end
-
end
-
-
1
def child name
-
60
absolute_name = @context_card.name.field_name name
-
60
if @keys.include? absolute_name.key
-
57
absolute_name
-
else
-
3
relative_child name
-
end
-
end
-
-
1
def relative_child name
-
3
@context_card.name.relative_field_name name
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Subcards
-
# Methods for removing/clearing subcards
-
1
module Remove
-
1
def remove_child cardish
-
child = cardish.is_a?(Card) ? cardish : child(cardish)
-
remove child
-
end
-
1
alias_method :remove_field, :remove_child
-
-
1
def remove name_or_card
-
1
key = subcard_key name_or_card
-
1
return unless @keys.include? key
-
-
1
@keys.delete key
-
1
clear_key key
-
end
-
-
1
def clear
-
@keys.each { |key| clear_key key }
-
@keys = ::Set.new
-
end
-
-
1
def clear_key key
-
1
if (subcard = fetch_subcard key)
-
1
Director.deep_delete subcard.director
-
1
subcard.current_action&.delete
-
end
-
1
Card.cache.soft.delete key
-
1
subcard
-
end
-
-
1
def deep_clear cleared=::Set.new
-
each_card do |card|
-
next if cleared.include? card.id
-
-
cleared << card.id
-
card.subcards.deep_clear cleared
-
end
-
clear
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
module Version
-
1
class << self
-
1
def release
-
31
@@version ||= File.read(File.expand_path("../../VERSION", __dir__)).strip
-
end
-
end
-
end
-
end
-
1
class Card
-
# Card::View manages {Options view options}, {Cache view caching}, and
-
# {Permission view permissions}.
-
#
-
# View objects, which are instantiated whenever a view is rendered, are available as
-
# in views and other format methods. The view objects can be accessed using `#voo`.
-
# We sometimes feebly pretend VOO is an acronym for "view option object," but really
-
# we just needed a way not to confuse these Card::View options with the countless
-
# references to viewnames that naturally arise when rendering views within views within
-
# views.
-
#
-
# When view A renders view B within the same format object, A's voo is the parent of
-
# B's voo. When card C nests card D, a new (sub)format object is initialized. C is then
-
# the parent _format_ of D, but D has its own root voo.
-
#
-
# So a lineage might look something like this:
-
#
-
# `F1V1 -> F1V2 -> F1V3 -> F2V1 -> F2V2 -> F3V1 ...`
-
#
-
#
-
1
class View
-
1
include Options
-
1
include View::Cache
-
1
include Classy
-
1
include Permission
-
-
1
extend View::Cache::ClassMethods
-
-
1
attr_reader :format, :parent, :card
-
-
1
class << self
-
# @return [Symbol] viewname as Symbol
-
1
def normalize view
-
28904
view.present? ? view.to_sym : nil
-
end
-
-
# @return [Array] list of viewnames as Symbols
-
1
def normalize_list val
-
44577
case val
-
44410
when NilClass then []
-
23
when Array then val
-
20
when String then val.split(/[\s,]+/)
-
124
when Symbol then [val]
-
else raise Card::Error, "bad show/hide argument: #{val}"
-
end
-
end
-
end
-
-
# @param format [Card::Format]
-
# @param view [Symbol] viewname. Note: Card::View is initialized without a view
-
# when `voo` is called outside of a render,
-
# eg `subformat(cardname).method_with_voo_reference`.
-
# @param raw_options [Hash]
-
# @param parent [Card::View] (optional)
-
1
def initialize format, view, raw_options={}, parent=nil
-
20912
@format = format
-
20912
@raw_view = view
-
20912
@raw_options = raw_options
-
20912
@parent = parent
-
-
20912
@card = @format.card
-
20912
normalize_options
-
end
-
-
# handle rendering, including optional visibility, permissions, and caching
-
# @return [rendered view or a stub]
-
1
def process
-
20887
return if process_live_options == :hide
-
-
40335
fetch { yield ok_view }
-
end
-
-
# the view to "attempt". Typically the same as @raw_view, but @raw_view can
-
# be overridden, eg for the main view (top view of the main card on a page)
-
# @return [Symbol] view name
-
1
def requested_view
-
162288
@requested_view ||= View.normalize live_options[:view]
-
end
-
-
# the final view. can be different from @requested_view when there are
-
# issues with permissions, recursions, unknown cards, etc.
-
# @return [Symbol] view name
-
1
def ok_view
-
60540
@ok_view ||= format.monitor_depth { altered_view || requested_view }
-
end
-
-
# @return [Card::View]
-
1
def root
-
@root = parent ? parent.root : self
-
end
-
-
# @return [true/false]
-
1
def root?
-
4
!parent
-
end
-
-
# the root voo of the root format
-
1
def deep_root
-
format.root.voo
-
end
-
-
# neither view nor format has a parent
-
# @return [true/false]
-
1
def deep_root?
-
19
!parent && !format.parent
-
end
-
-
# next voo object found tracing ancestry through parent voos and/or parent formats
-
# @return [Card::View]
-
1
def next_ancestor across_format=true
-
164
parent || (across_format && next_format_ancestor) || nil
-
end
-
-
# voo object of format's parent
-
1
def next_format_ancestor
-
10112
format.parent&.voo
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
# View::Cache supports smart card view caching.
-
#
-
# The basic idea is that when view caching is turned on (via `config.view_cache`),
-
# we try to cache a view whenever it's "safe" to do so. We will include everything
-
# inside that view (including other views) until we find something that isn't safe.
-
# When something isn't safe, we render a {Stub stub}: a placeholder
-
# with all the info we need to come back and replace it with the correct content
-
# later. In this way it is possible to have many levels of cached views within
-
# cached views.
-
#
-
# Here are some things that we never consider safe to cache:
-
#
-
# 1. a view explicitly configured _never_ to be cached
-
# 2. a view of a card with view-relevant permission restrictions
-
# 3. a view other than the requested view (eg a denial view)
-
# 4. a card with unsaved content changes
-
#
-
# We also consider it unsafe to cache a view of one card within a view of a different
-
# card, so nests are always handled with a stub.
-
#
-
# ## Cache configuration
-
#
-
# Cache settings (#5) can be configured in the
-
# {Set::Format::AbstractFormat#view view definition}
-
# and (less commonly) as a {Card::View::Options view option}.
-
#
-
# By far, the most common explicit caching configuration is `:never`. This setting
-
# is used to prevent over-caching, which becomes problematic when data changes
-
# do not clear the cache.
-
#
-
# Generally speaking, a card is smart about clearing its own view caches when
-
# anything about the card itself. So when I update the card "Johnny", all the cached
-
# views of "Johnny" are cleared. Similarly, changes to structure rules and other
-
# basic patterns are typically well managed by the caching system.
-
#
-
# However, there are many other potential changes that views cannot detect. Views that
-
# are susceptible to these "cache hazards" should be configured with `cache: :never`.
-
#
-
# ## Cache hazards
-
#
-
# If a view contains any of the following cache hazards, it would be wise to consider
-
# a `cache: :never` configuration:
-
#
-
# - dynamic searches (eg `Card.search`) whose results may change
-
# - live timestamps (eg `Time.now`)
-
# - environmental variables (eg `Env.params`)
-
# - any variables altered in one view and used in another (eg `@myvar`)
-
# - other cards' properties (eg `Card["random"].content`)
-
#
-
# What all of the above have in common is that they involve changes about which the
-
# view caching system is unaware. This means that whether the cache hazard is
-
# rendered directly in a view or just used in its logic, it can change in a way
-
# that _should_ change the view but _won't_ change the view if it's cached.
-
#
-
# ## Altering cached views
-
#
-
# Whereas ignoring cache hazards may cause over-caching, altering cached views
-
# may cause outright errors. If a view directly alters a rendered view,
-
# it may be dangerous to cache.
-
#
-
# # obviously safe to cache
-
# view(:x) { "ABC" }
-
#
-
# # also safe, because x is NOT altered
-
# view(:y) { render_x + "DEF" }
-
#
-
# # unsafe and thus never cached, because x is altered
-
# view(:z, cache: :never) { render_x.reverse }
-
#
-
# Specifically, the danger is that the inner view will be rendered as a stub,
-
# and the out view will end up altering the stub and not the view.
-
#
-
# Although alterations should be considered dangerous, they are actually only
-
# problematic in situations where the inner view might sometimes render a stub.
-
# If the outer view is rendering a view of the _same card_ with all the _same view
-
# settings_ (perms, unknown, etc), there will be no stub and thus no error.
-
# Remember, however, that a view on a narrow set may inherit view settings
-
# from a general set. To be confident that a view alteration is safe, all inherited
-
# settings must be taken into account.
-
#
-
# ## Caching Best Practices
-
#
-
# Here are some good rules of thumb to make good use of view caching:
-
#
-
# 1. *Use nests.* If you can show the content of a different card with a nest rather
-
# than by showing the content directly, the caching system will be much
-
# happier with you.
-
#
-
# view :bad_idea, cache: :never do
-
# Card["random"].content
-
# end
-
#
-
# view :good_idea do
-
# nest :random, view: :core
-
# end
-
#
-
# 2. *Isolate the cache hazards.* Consider the following variants:
-
#
-
# view :bad_idea, cache: :never do
-
# if morning_for_user?
-
# expensive_good_morning
-
# else
-
# expensive_good_afternoon
-
# end
-
# end
-
#
-
# view :good_idea, cache: :never do
-
# morning_for_user? ? render_good_morning : render_good_afternoon
-
# end
-
#
-
# In the first example, we have to generate expensive greetings every time we
-
# render the view. In the second, only the test is not cached.
-
#
-
# 3. If you must alter view results, consider *generating the view content
-
# in a separate method.*
-
#
-
# # First Attempt
-
#
-
# view :hash_it_in do
-
# { cool: false }
-
# end
-
#
-
# view :bad_idea, cache: :never do
-
# render_badhash.merge sucks: true
-
# end
-
#
-
#
-
# #Second Attempt
-
#
-
# view :hash_it_out do
-
# hash_it_out
-
# end
-
#
-
# def hash_it_out
-
# { cool: true }
-
# end
-
#
-
# view :good_idea do
-
# hash_it_out.merge rocks: true
-
# end
-
#
-
# The first attempt will work fine with caching off but is risky with caching on.
-
# The second is safe with caching on.
-
#
-
# ## Optimizing with `:always`
-
#
-
# It is never strictly necessary to use `cache: :always`, but this setting can help
-
# optimize your use of the caching system in some cases.
-
#
-
# Consider the following views:
-
#
-
# view(:hat) { "hat" } # ...but imagine this is computationally expensive
-
#
-
# view(:old_hat) { "old #{render_hat}" }
-
# view(:new_hat) { "new #{render_hat}" }
-
# view(:red_hat) { "red #{render_hat}" }
-
# view(:blue_hat) { "blue #{render_hat}" }
-
#
-
# Whether "hat" uses `:standard` or `:always`, the hat varieties (old, new, etc...)
-
# will fully contain the rendered hat view in their cache. However, with `:standard`,
-
# the other views will each re-render hat without attempting to cache it separately
-
# or to find it in the cache. This could lead to man expensive renderings of the
-
# "hat" view. By contrast, if the cache setting is `:always`, then hat will be
-
# cached and retrieved even when it's rendered inside another cached view.
-
#
-
1
module Cache
-
1
require "card/view/cache/cache_action"
-
1
require "card/view/cache/stub"
-
-
1
include CacheAction
-
1
include Stub
-
-
1
private
-
-
# render or retrieve view (or stub) with current options
-
# @param block [Block] code block to render
-
# @return [rendered view or stub]
-
1
def fetch &block
-
20168
case cache_action
-
20167
when :yield then yield # simple render
-
1
when :cache_yield then cache_render(&block) # render to/from cache
-
when :stub then stub # render stub
-
end
-
end
-
-
# Fetch view via cache and, when appropriate, render its stubs
-
#
-
# If this is a free cache action (see CacheAction), we go through the stubs and
-
# render them now.
-
# If the cache is active (ie, we are inside another view), we do not worry about
-
# stubs but keep going, because the free cache we're inside will take care of
-
# those stubs.
-
#
-
# @return [String (usually)] rendered view
-
1
def cache_render
-
1
cached_view = cache_fetch { yield }
-
1
cache_active? ? cached_view : format.stub_render(cached_view)
-
end
-
-
# Is there already a view cache in progress on which this one depends?
-
#
-
# Note that if you create a brand new independent format object
-
# (ie, not a subformat)
-
# its activity will be treated as unrelated to this caching/rendering.
-
#
-
# @return [true/false]
-
1
def cache_active?
-
19
deep_root? ? false : self.class.caching?
-
end
-
-
# If view is cached, retrieve it. Otherwise render and store it.
-
# Uses the primary cache API.
-
1
def cache_fetch
-
1
caching do
-
1
ensure_cache_key
-
1
self.class.cache.fetch cache_key do
-
yield
-
end
-
end
-
end
-
-
# keep track of nested cache fetching
-
1
def caching
-
2
self.class.caching(self) { yield }
-
end
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# VIEW CACHE KEY
-
-
1
def cache_key
-
2
@cache_key ||= [
-
card_cache_key, format.class, format.nest_mode, options_for_cache_key
-
].map(&:to_s).join "-"
-
end
-
-
1
def card_cache_key
-
1
card.real? ? card.id : "#{card.key}-#{card.type_id}"
-
end
-
-
# Registers the cached view for later clearing in the event of related card changes
-
1
def ensure_cache_key
-
1
card.ensure_view_cache_key cache_key
-
end
-
-
1
def options_for_cache_key
-
1
hash_for_cache_key(live_options) + hash_for_cache_key(viz_hash)
-
end
-
-
1
def hash_for_cache_key hash
-
2
hash.keys.sort.map do |key|
-
6
option_for_cache_key key, hash[key]
-
end.join ";"
-
end
-
-
1
def array_for_cache_key array
-
# TODO: needs better handling of edit_structure
-
# currently we pass complete structure as nested array
-
array.map do |item|
-
item.is_a?(Array) ? item.join(":") : item.to_s
-
end.sort.join ","
-
end
-
-
1
def option_for_cache_key key, value
-
6
"#{key}:#{option_value_to_string value}"
-
end
-
-
1
def option_value_to_string value
-
6
case value
-
when Hash then "{#{hash_for_cache_key value}}"
-
when Array then array_for_cache_key(value)
-
6
else value.to_s
-
end
-
end
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# cache-related Card::View class methods
-
1
module ClassMethods
-
1
def cache
-
4
Card::Cache[Card::View]
-
end
-
-
1
def caching?
-
17
!@caching.nil?
-
end
-
-
1
def caching voo
-
1
old_caching = @caching
-
1
@caching = voo
-
1
yield
-
ensure
-
1
@caching = old_caching
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
1
module Cache
-
# determine action to be used in #fetch
-
1
module CacheAction
-
1
private
-
-
# course of action based on config/status/options
-
# @return [Symbol] :yield, :cache_yield, or
-
1
def cache_action
-
20168
log_cache_action do
-
20168
send "#{cache_status}_cache_action"
-
end
-
end
-
-
1
def log_cache_action
-
20168
action = yield
-
# TODO: make configurable
-
# ...or better yet, integrate into performance logger...
-
# Rails.logger.warn "VIEW CACHE #{cache_active? ? '-->' : ''}[#{action}] "\
-
# "(#{card.name}##{requested_view})"
-
20168
action
-
end
-
-
# @return [Symbol] :off, :active, or :free
-
1
def cache_status
-
case
-
20168
when !cache_on?
-
20150
:off # view caching is turned off, format- or system-wide
-
when cache_active?
-
:active # another view cache is in progress (current view is inside it)
-
else
-
18
:free # no other cache in progress
-
end
-
end
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# CACHE STATUS: OFF
-
# view caching is turned off, format- or system-wide
-
-
# @return [True/False]
-
1
def cache_on?
-
20168
Card.config.view_cache && format.class.view_caching?
-
end
-
-
# always skip all the magic
-
1
def off_cache_action
-
20150
:yield
-
end
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# CACHE STATUS: FREE
-
# caching is on; no other cache in progress
-
-
# @return [Symbol]
-
1
def free_cache_action
-
18
free_cache_ok? ? :cache_yield : :yield
-
end
-
-
# @return [True/False]
-
1
def free_cache_ok?
-
18
cache_setting != :never && clean_enough_to_cache?
-
end
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# CACHE STATUS: ACTIVE
-
# another view cache is in progress; this view is inside it
-
-
# @return [Symbol]
-
1
def active_cache_action
-
active_cache_ok? ? active_cache_action_from_setting : :stub
-
end
-
-
# @return [True/False]
-
1
def active_cache_ok?
-
return false unless parent && clean_enough_to_cache?
-
return true if normalized_options[:skip_perms]
-
-
active_cache_permissible?
-
end
-
-
# apply any permission checks required by view.
-
# (do not cache views with nuanced permissions)
-
1
def active_cache_permissible?
-
case view_perms
-
when :none then true
-
when parent.view_perms then true
-
when Symbol then format.anyone_can?(view_perms)
-
else false
-
end
-
end
-
-
# determine the cache action from the cache setting
-
# (assuming cache status is "active")
-
# @return [Symbol] cache action
-
1
def active_cache_action_from_setting
-
level = ACTIVE_CACHE_LEVEL[cache_setting]
-
level || raise("unknown cache setting: #{cache_setting}")
-
end
-
-
ACTIVE_CACHE_LEVEL =
-
1
{ always: :cache_yield, standard: :yield, never: :stub }.freeze
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# SHARED METHODS
-
-
# @return [Symbol] :standard, :always, or :never
-
1
def cache_setting
-
18
format.view_cache_setting requested_view
-
end
-
-
# altered view requests and altered cards are not cacheable
-
# @return [True/False]
-
1
def clean_enough_to_cache?
-
# requested_view == ok_view && !card.unknown? && !card.db_content_changed?
-
5
requested_view == ok_view && card.view_cache_clean?
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
1
module Cache
-
# A "stub" is a placeholder for a card view.
-
#
-
# Cached views use stubs so that _nesting_ content can remained cached
-
# even while _nested_ content changes. The nested content's place is held
-
# by a stub.
-
#
-
# A stub must contain all the information necessary to produce the view as intended.
-
1
module Stub
-
1
private
-
-
# @return [String]
-
1
def stub
-
"(StUb#{stub_hash.to_json}sTuB)".html_safe
-
end
-
-
1
def bin_to_hex string
-
string.unpack("H*").first
-
end
-
-
# @return [Hash]
-
1
def stub_hash
-
{ cast: stub_cast,
-
view_opts: normalized_options.merge(normalized_visibility_options),
-
format_opts: { nest_mode: format.nest_mode,
-
override: root?,
-
context_names: format.context_names } }
-
# nest mode handling:
-
#
-
# Typically modes override views on nests, but stubs create non-standard nests.
-
# Mode-based view overrides should NOT apply to standard render calls that have
-
# been replaced with stubs - only to standard nest calls. The override value
-
# is used to retain this distinction.
-
end
-
-
1
def stub_cast
-
cast = card.cast
-
cast.delete :content if cast[:content].nil?
-
cast
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
# API to change css classes in other places
-
1
module Classy
-
# Add additional css classes to a css class
-
#
-
# Example
-
# class_up "card-slot", "card-dark text-muted"
-
#
-
# If a view later adds the css "card-slot" to a html tag with
-
#
-
# classy("card-slot")
-
#
-
# then all additional css classes will be added.
-
#
-
# The scope when these additional classes apply can be restricted
-
# @param klass [String, Symbol] the css class to be enriched with additional classes
-
# @param classier [String, Array<String>] additional css classes
-
# @param scope [Symbol]
-
# :view only in the same view
-
# :subviews the same and all subviews; not in nests or where its nested
-
# :format all views, sub and parent views; not in nests or where its nested
-
# :nests the same as :format but also in nests
-
# :single_use the same as :nests but is removed after the first use
-
# :global always everywhere
-
1
def class_up klass, classier, scope=:subviews
-
876
klass = klass.to_s
-
-
876
storage_voo(scope).add_extra_classes klass, classier, scope
-
end
-
-
1
def class_down klass, classier
-
101
remove_extra_classes klass, classier, :private
-
end
-
-
1
def with_class_up klass, classier, scope=:subviews
-
101
class_up klass, classier, scope
-
101
yield
-
ensure
-
101
class_down klass, classier
-
end
-
-
# don't use in the given block the additional class that
-
# was added to `klass`
-
1
def without_upped_class klass
-
tmp_class = class_list.delete klass
-
result = yield tmp_class
-
class_list[klass] = tmp_class
-
result
-
end
-
-
1
def classy *classes
-
3550
classes = Array.wrap(classes).flatten
-
3550
[classes, extra_classes(classes)].flatten.compact.join " "
-
end
-
-
1
def add_extra_classes key, classier, scope
-
876
type = class_list_type scope
-
-
876
class_list(type)[key] =
-
[class_list(type)[key], classier].flatten.compact.join(" ")
-
end
-
-
# remove classes everywhere where they are visible for the given scope
-
1
def remove_extra_classes klass, classier, type
-
# TODO: scope handling
-
# Method is not used and maybe no longer necessary with the scope feature
-
# for class_up.
-
-
# It's no longer sufficient to remove only public classes for ancestors.
-
# Needs an approach similar to extra_classes with the "space" argument
-
164
next_ancestor&.remove_extra_classes klass, classier, :public
-
-
164
cl = class_list type
-
164
return unless cl[klass]
-
-
if cl[klass] == classier
-
cl.delete klass
-
else
-
cl[klass].gsub!(/#{classier}\s?/, "")
-
end
-
end
-
-
1
def extra_classes klass
-
3550
klass = klass.first if klass.is_a?(Array)
-
3550
klass = klass.to_s
-
-
3550
deep_extra_classes klass, :self
-
end
-
-
# recurse through voos and formats to find all extra classes
-
# @param space [:self, :self_format, :ancestor_format]
-
1
def deep_extra_classes klass, space
-
22201
[self_extra_classes(klass, space),
-
ancestor_extra_classes(klass, space)].flatten.compact
-
end
-
-
1
private
-
-
1
def ancestor_extra_classes klass, space
-
22201
if parent
-
12237
parent_space = space == :self ? :self_format : :ancestor_format
-
12237
parent.deep_extra_classes(klass, parent_space)
-
else
-
9964
next_format_ancestor&.deep_extra_classes(klass, :ancestor_format)
-
end
-
end
-
-
1
def storage_voo scope
-
# When we climb up the voo tree and cross a nest boundary then we can jump only
-
# to the root voo of the parent format. Hence we have to add classes to the root
-
# if we want them to be found by nests.
-
876
case scope
-
876
when :view, :subviews then self
-
when :format, :nests, :single_use then root
-
when :global then deep_root
-
else
-
raise ArgumentError, "invalid class_up scope: #{scope}"
-
end
-
end
-
-
1
def self_extra_classes klass, space
-
53691
classes = ok_types(space).map { |ot| class_list(ot)[klass] }
-
22201
return classes unless class_list(:single_use)&.key? klass
-
-
[classes, class_list(:single_use).delete(klass)]
-
end
-
-
1
def ok_types space
-
22201
case space
-
16462
when :ancestor_format then [:public]
-
2189
when :self_format then %i[public format_private]
-
3550
when :self then %i[public format_private private]
-
end
-
end
-
-
1
def class_list type=:private
-
55607
case type
-
when :private, :format_private, :public, :single_use
-
55607
@class_list ||= {}
-
55607
@class_list[type] ||= {}
-
else
-
raise ArgumentError, "#{type} not a valid class list"
-
end
-
end
-
-
# Translates scopes to the privacy types used to manage the class lists.
-
# A #classy calls looks in the following class_lists:
-
# private - only in the same voo
-
# format_private - the same voo and all parent voos in the same format
-
# public - in all voos in all parent formats
-
1
def class_list_type scope
-
876
case scope
-
when :view
-
1
:private
-
when :format, :subviews
-
875
:format_private
-
when :nests, :global
-
:public
-
when :single_use
-
:single_use
-
else
-
raise ArgumentError, "invalid class_up scope: #{scope}"
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
# Manages options for rendering card views
-
#
-
# Many options are available to sharks via nests. (See https://decko.org/Nest_Syntax)
-
#
-
# {{cardname|hide:menu}}
-
#
-
# These options and others are available to monkeys when rendering views
-
# via #render or #nest.
-
#
-
# nest "cardname", hide: :menu
-
# render :viewname, hide: :menu
-
#
-
1
module Options
-
# the keymap represents a 2x2 matrix, where the factors are
-
# (a) whether an option's value can be set by a shark via nests, and
-
# (b) whether subviews can inherit the option from a parent view.
-
#
-
# for sharks | not for sharks
-
# ________________________________
-
# inherit | both | heir
-
# don't inherit | shark | none
-
#
-
# (note: each option will likely some day merit its own object)
-
@keymap = {
-
1
shark: [
-
:view, # view to render
-
:nest_name, # name as used in nest
-
:nest_syntax, # full nest syntax
-
:wrap, # wrap the nest with a wrapper
-
:show, # render these views when optional
-
:hide # do not render these views when optional
-
], # show/hide can be view (Symbol), list of views (Array),
-
# or comma separated views (String)
-
# NOTE: although show and hide are in this non-inheriting group, they are
-
# actually inherited, just not through the standard mechanism. Because, well,
-
# they're weird. (See process_visibility)
-
heir: [
-
:main, # format object is page's "main" object (Boolean)
-
:home_view, # view for slot to return to when no view specified
-
:edit_structure, # use a different structure for editing (Array)
-
:cql, # contextual cql alterations for search cards (Hash)
-
:action_id, # a Card::Action id (Integer)
-
:content_opts # options for Card::Content.new
-
# :context_names # names used to contextualize titles
-
],
-
both: [
-
:help, # cue text when editing
-
:structure, # overrides the content of the card
-
:title, # overrides the name of the card
-
:variant, # override the canonical version of the name with a different
-
# variant
-
:input_type, # inline_nests makes a form within standard content (Symbol)
-
:type, # set the default type of new cards
-
:size, # set an image size
-
# (also used for character limit in one_line_content)
-
:params, # parameters for add button. deprecated!
-
:items, # options for items (Hash)
-
:cache, # change view cache behaviour
-
# (Symbol<:always, :standard, :never>)
-
:edit, # edit mode
-
# (Symbol<:inline, :standard, :full>)
-
:separator, # item separator in certain lists
-
:filter
-
],
-
none: [
-
:skip_perms, # do not check permissions for this view (Boolean)
-
:main_view, # this is main view of page (Boolean)
-
:layout #
-
]
-
}
-
# Note: option values are strings unless otherwise noted
-
-
1
class << self
-
1
attr_reader :keymap
-
-
1
def add_option name, type
-
1
raise "invalid option type: #{type}" unless @keymap.key?(type)
-
-
1
@keymap[type] << name
-
1
reset_key_lists
-
1
VooApi.define_getter name
-
1
VooApi.define_setter name
-
end
-
end
-
-
1
extend KeyLists
-
1
include VooApi
-
1
include Visibility
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
1
module Options
-
1
module KeyLists
-
# all standard option keys
-
# @return [Array]
-
1
def all_keys
-
55357
@all_keys ||= keymap.each_with_object([]) { |(_k, v), a| a.push(*v) }
-
end
-
-
# keys whose values can be set by Sharks in card nests
-
# @return [Array]
-
1
def shark_keys
-
2941
@shark_keys ||= ::Set.new(keymap[:both]) + keymap[:shark]
-
end
-
-
# keys that follow simple standard inheritance pattern from parent views
-
# @return [Array]
-
1
def heir_keys
-
11802
@heir_keys ||= ::Set.new(keymap[:both]) + keymap[:heir]
-
end
-
-
# Keys that can be read or written via accessors
-
# @return [Array]
-
1
def accessible_keys
-
3
all_keys - [ # (all but the following)
-
:view, # view is accessed as requested_view or ok_view and cannot be
-
# directly manipulated
-
:show, :hide # these have a more extensive API (see Card::View::Visibility)
-
]
-
end
-
-
1
def slot_keys
-
907
@slot_keys ||= all_keys - [:skip_perms]
-
end
-
-
1
def reset_key_lists
-
1
@all_keys = nil
-
1
@shark_keys = nil
-
1
@heir_keys = nil
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
1
module Options
-
# manages showing and hiding optional view renders
-
1
module Visibility
-
# tracks show/hide value for each view with an explicit setting
-
# eg { toggle: :hide }
-
1
def viz_hash
-
113322
@viz_hash ||= {}
-
end
-
-
# test methods
-
-
1
def hide? view
-
21869
viz_hash[view&.to_sym] == :hide
-
end
-
-
1
def show? view
-
1174
!hide? view
-
end
-
-
# write methods
-
-
1
def show *views
-
105
viz views, :show
-
end
-
-
1
def hide *views
-
619
viz views, :hide
-
end
-
-
# force write methods
-
-
1
def show! *views
-
11
viz views, :show, true
-
end
-
-
1
def hide! *views
-
467
viz views, :hide, true
-
end
-
-
# advanced write method
-
1
VIZ_SETTING = { show: :show, true => :show,
-
hide: :hide, false => :hide, nil => :hide }.freeze
-
-
1
def viz views, setting, force=false
-
65630
Array.wrap(views).flatten.each do |view|
-
21522
view = view.to_sym
-
21522
next if !force && viz_hash[view]
-
-
21451
viz_hash[view] = VIZ_SETTING[setting]
-
end
-
end
-
-
1
def visible? view
-
77
viz view, yield unless viz_hash[view]
-
77
show? view
-
end
-
-
# test whether view is optional
-
# (@optional is set in normalize_options
-
# @return [true/false]
-
1
def optional?
-
20902
@optional
-
end
-
-
# translate raw hide, show options (which can be strings, symbols,
-
# arrays, etc)
-
1
def process_visibility
-
22282
viz_hash.reverse_merge! parent.viz_hash if parent
-
22282
process_visibility_options live_options
-
22282
viz requested_view, @optional if @optional && !viz_hash[requested_view]
-
end
-
-
1
private
-
-
# if true, #process returns nil
-
1
def hide_requested_view?
-
20902
optional? && hide?(requested_view)
-
end
-
-
# takes an options_hash and processes it to update viz_hash
-
1
def process_visibility_options options_hash
-
22282
%i[hide show].each do |setting|
-
44564
views = View.normalize_list(options_hash.delete(setting)).map(&:to_sym)
-
44564
viz views, setting, true
-
end
-
end
-
-
1
def normalized_visibility_options
-
viz_hash.each_with_object({}) do |(key, val), hash|
-
hash[val] ||= []
-
hash[val] << key
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
1
module Options
-
# VooApi methods let developers use view options dynamically.
-
1
module VooApi
-
# There are two primary options hashes:
-
-
# - @normalized_options are determined upon initialization and do not change
-
# after that.
-
# @return [Hash] options
-
1
attr_reader :normalized_options
-
-
1
class << self
-
1
def included base
-
# Developers can also set most options directly via accessors,
-
# eg voo.title = "King"
-
# :view, :show, and :hide have non-standard access (see #accessible_keys)
-
-
1
base.accessible_keys.each do |option_key|
-
25
define_getter option_key unless option_key == :items
-
25
define_setter option_key
-
end
-
end
-
-
1
def define_getter option_key
-
25
define_method option_key do
-
47505
live_options[option_key]
-
end
-
end
-
-
1
def define_setter option_key
-
26
define_method "#{option_key}=" do |value|
-
128
live_options[option_key] = special_option_value(option_key, value) || value
-
end
-
end
-
end
-
-
# "items", the option used to configure views of each of a list of cards, is
-
# currently the only Hash option (thus this accessor override)
-
# @return [Hash]
-
1
def items
-
281
live_options[:items] ||= {}
-
end
-
-
# options to be used in data attributes of card slots (normalized options
-
# with standard keys)
-
# FIXME: what we really want is options as they were when render was called.
-
# normalized is wrong because it can get changed before render. live is wrong
-
# because they can get changed after. current solution is a compromise.
-
# @return [Hash]
-
1
def slot_options
-
617
normalized_options.merge(view: requested_view).slice(*Options.slot_keys)
-
end
-
-
# ACCESSOR_HELPERS
-
# methods that follow the normalize_#{key} pattern are called by accessors
-
# (arguably that should be done during normalization!)
-
-
1
def normalize_special_options! opts
-
20915
opts.each do |option_key, value|
-
50474
new_value = special_option_value option_key, value
-
50474
opts[option_key] = new_value if new_value
-
end
-
end
-
-
1
def special_option_value option_key, value
-
50602
try "normalize_#{option_key}", value
-
end
-
-
1
def normalize_input_type value
-
3
value&.to_sym
-
end
-
-
1
def normalize_edit value
-
41
value&.to_sym
-
end
-
-
1
def normalize_cache value
-
4
value&.to_sym
-
end
-
-
1
def normalize_wrap value
-
44
value = value.split(",").map(&:strip) if value.is_a? String
-
44
Array.wrap(value).compact.flatten
-
end
-
-
1
protected
-
-
# - @live_options are dynamic and can be altered by the "voo" API at any time.
-
# Such alterations are NOT used in the stub of the current voo, but they
-
# ARE inherited by children voos.
-
#
-
# @return [Hash]
-
1
def live_options
-
315367
@live_options ||= process_live_options
-
end
-
-
1
private
-
-
# option normalization includes standardizing options into a hash with
-
# symbols as keys, managing standard view inheritance, and special
-
# handling for main_views.
-
1
def normalize_options
-
20912
@normalized_options = opts = options_to_hash @raw_options.clone
-
20912
normalize_special_options! opts
-
20912
@optional = opts.delete(:optional) || false
-
20912
add_implicit_options!
-
20912
inherit_options_from_parent!
-
20912
validate_options! opts
-
20912
opts
-
end
-
-
1
def add_implicit_options!
-
20912
@normalized_options[:view] = @raw_view
-
20912
@normalized_options[:main] = true if format.main?
-
# opts[:context_names] = format.context_names
-
end
-
-
# typically options are already a hash. this also handles an array of
-
# hashes and nil.
-
1
def options_to_hash opts
-
20912
case opts
-
when ActionController::Parameters
-
opts.to_unsafe_h.deep_symbolize_keys
-
20912
when Hash then opts.deep_symbolize_keys!
-
when Array then opts[0].merge(opts[1]).deep_symbolize_keys!
-
when nil then {}
-
else raise Card::Error, "bad view options: #{opts}"
-
end
-
end
-
-
# standard inheritance from parent view object
-
1
def inherit_options_from_parent!
-
20912
return unless parent
-
-
11802
Options.heir_keys.each do |option_key|
-
224238
inherit_from_parent! option_key
-
end
-
end
-
-
1
def inherit_from_parent! option_key
-
224238
return unless (parent_value = parent.live_options[option_key])
-
-
11972
@normalized_options[option_key] ||= parent_value
-
end
-
-
1
def process_live_options
-
20902
@live_options = normalized_options.clone
-
20902
process_main_nest_options
-
20902
process_before_view
-
20902
process_visibility
-
20902
return :hide if hide_requested_view? # bail to avoid unnecessary processing
-
-
20185
process_view_wrappers
-
20183
@live_options
-
end
-
-
# This method triggers the "before" blocks which can alter the @live_options
-
# hash both directly and indirectly (via the voo API)
-
1
def process_before_view
-
20902
format.before_view requested_view
-
end
-
-
# adds the wrappers assigned to ok_view in view definition
-
1
def process_view_wrappers
-
20185
view_wrappers = format.view_setting(:wrap, ok_view)
-
20183
return unless view_wrappers.present?
-
-
436
@live_options[:wrap] = Array.wrap(@live_options[:wrap])
-
436
if view_wrappers.is_a? ::Hash
-
239
view_wrappers.each_pair do |name, opts|
-
240
@live_options[:wrap] << [name, opts]
-
end
-
else
-
197
@live_options[:wrap] += Array.wrap(view_wrappers)
-
end
-
end
-
-
# merge the options of the main nest into the @live_options
-
# They are not processed in normalize_options so that
-
# they're NOT locked in the stub.
-
1
def process_main_nest_options
-
20902
@live_options.merge! format.main_nest_options if @live_options[:main_view]
-
end
-
-
1
def validate_options! opts
-
20912
return unless (foreign_opts = foreign_options_in opts)
-
-
# TODO: this should raise a UserError if the options come directly from params
-
# (eg, mycard?slot[badoption]=true should not be treated as a server error)
-
raise Card::Error, "illegal view options: #{foreign_opts}"
-
end
-
-
# find non-standard option in Hash
-
# @param opts [Hash] options hash
-
# @return [Hash] options Hash
-
1
def foreign_options_in opts
-
76255
foreign_opts = opts.reject { |k, _v| Options.all_keys.include? k }
-
20912
foreign_opts.empty? ? nil : foreign_opts
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class View
-
# View permissions support view-specific permission handling
-
#
-
# Views can be configured in {Set::Format::AbstractFormat#view view definitions}
-
# with the `perms` directive, eg
-
#
-
# # only render if user has permission to update card
-
# view :myview, perms: :update do...
-
1
module Permission
-
1
def view_perms
-
44650
@view_perms = setting(:perms) || :read
-
end
-
-
1
private
-
-
1
def altered_view
-
20183
return if skip_check?
-
13877
alter_unknown || denial
-
end
-
-
1
def skip_check?
-
20183
normalized_options[:skip_perms] || view_perms == :none
-
end
-
-
1
def setting setting_name, view=nil
-
58527
view ||= requested_view
-
58527
format.view_setting setting_name, view
-
end
-
-
# by default views can't handle unknown cards, but this can be overridden in
-
# view definitions with the `unknown` directive
-
1
def alter_unknown
-
13877
setting = setting(:unknown)
-
13877
return if setting == true || card.known?
-
73
setting.is_a?(Symbol) ? setting : format.view_for_unknown(requested_view)
-
end
-
-
1
def denial
-
13804
return unless (task = denied_task)
-
-
111
format.view_for_denial requested_view, task
-
end
-
-
1
def denied_task
-
13804
if view_perms.is_a? Proc
-
123
:read unless view_perms.call(format) # read isn't quite right
-
else
-
27362
Array.wrap(view_perms).find { |task| !format.ok? task }
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
class Content
-
1
module Chunk
-
# These are basic chunks that have a pattern and can be protected.
-
# They are used by rendering process to prevent wiki rendering
-
# occuring within literal areas such as <code> and <pre> blocks
-
# and within HTML tags.
-
1
class EscapedLiteral < Abstract
-
1
FULL_RE = { "[" => /\A\\\[\[[^\]]*\]\]/,
-
"{" => /\A\\\{\{[^\}]*\}\}/ }.freeze
-
1
Card::Content::Chunk.register_class self,
-
prefix_re: '\\\\(?:\\[\\[|\\{\\{)',
-
idx_char: '\\'
-
-
1
def self.full_re prefix
-
5
FULL_RE[prefix[1, 1]]
-
end
-
-
1
def interpret match, _content
-
5
@process_chunk = match[0].sub(/^\\(.)/, format.escape_literal('\1'))
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
class Content
-
1
module Chunk
-
# These are basic chunks that have a pattern and can be protected.
-
# This chunk is used for markdown processing to ensure that
-
# the escaping survives the markdown rendering.
-
1
class KeepEscapedLiteral < Abstract
-
1
FULL_RE = { "[" => /\A\\\[\[[^\]]*\]\]/,
-
"{" => /\A\\\{\{[^\}]*\}\}/ }.freeze
-
1
Card::Content::Chunk.register_class self,
-
prefix_re: '\\\\(?:\\[\\[|\\{\\{)',
-
idx_char: '\\'
-
-
1
def self.full_re prefix
-
2
FULL_RE[prefix[1, 1]]
-
end
-
-
1
def interpret match, _content
-
2
@process_chunk = match[0].sub(/^\\(.)/, '\\\\\\\\\1')
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
# require File.expand_path("../reference", __FILE__)
-
1
load File.expand_path("../reference.rb", __FILE__)
-
-
1
class Card
-
1
class Content
-
1
module Chunk
-
# extend ActiveSupport::Autoload
-
# autoload :Reference , "reference"
-
-
1
class Link < Card::Content::Chunk::Reference
-
1
CODE = "L".freeze # L for "Link"
-
1
attr_reader :link_text
-
# Groups: $1, [$2]: [[$1]] or [[$1|$2]] or $3, $4: [$3][$4]
-
1
Card::Content::Chunk.register_class self,
-
prefix_re: '\\[\\[',
-
full_re: /\A\[\[([^\]]+)\]\]/,
-
idx_char: "["
-
1
def reference_code
-
1714
CODE
-
end
-
-
1
def interpret match, _content
-
target, @link_text =
-
2606
if (raw_syntax = match[1])
-
2606
if (i = divider_index(raw_syntax)) # [[A | B]]
-
556
[raw_syntax[0..(i - 1)], raw_syntax[(i + 1)..-1]]
-
else # [[ A ]]
-
2050
[raw_syntax, nil]
-
end
-
end
-
-
2606
@link_text = objectify @link_text
-
2606
if target.match? %r{^(/|https?:|mailto:)}
-
673
@explicit_link = objectify target
-
else
-
1933
@name = target
-
end
-
end
-
-
1
def divider_index string
-
# there's probably a better way to do the following.
-
# point is to find the first pipe that's not inside an nest
-
2606
return unless string.index "|"
-
556
string_copy = string.dup
-
556
string.scan(/\{\{[^\}]*\}\}/) do |incl|
-
7
string_copy.gsub! incl, ("x" * incl.length)
-
end
-
556
string_copy.index "|"
-
end
-
-
# view options
-
1
def options
-
379
link_text ? { title: link_text } : {}
-
end
-
-
1
def objectify raw
-
3279
return unless raw
-
1229
raw.strip!
-
1229
if raw =~ /(^|[^\\])\{\{/
-
7
Card::Content.new raw, format
-
else
-
1222
raw
-
end
-
end
-
-
1
def render_link view: :link, explicit_link_opts: {}
-
733
@link_text = render_obj @link_text
-
-
733
if @explicit_link
-
373
@explicit_link = render_obj @explicit_link
-
373
format.link_to_resource @explicit_link, @link_text, explicit_link_opts
-
360
elsif @name
-
360
format.with_nest_mode :normal do
-
360
format.nest referee_name, options.merge(view: view)
-
end
-
end
-
end
-
-
1
def link_target
-
2
if @explicit_link
-
2
render_obj @explicit_link
-
elsif @name
-
referee_name
-
end
-
end
-
-
1
def process_chunk
-
489
@process_chunk ||= render_link
-
end
-
-
1
def inspect
-
"<##{self.class}:e[#{@explicit_link}]n[#{@name}]l[#{@link_text}]" \
-
"p[#{@process_chunk}] txt:#{@text}>"
-
end
-
-
1
def replace_reference old_name, new_name
-
88
replace_name_reference old_name, new_name
-
88
replace_link_text old_name, new_name
-
@text =
-
88
@link_text.nil? ? "[[#{referee_name}]]" : "[[#{referee_name}|#{@link_text}]]"
-
end
-
-
1
def replace_link_text old_name, new_name
-
88
if @link_text.is_a?(Card::Content)
-
1
@link_text.find_chunks(Card::Content::Chunk::Reference).each do |chunk|
-
1
chunk.replace_reference old_name, new_name
-
end
-
87
elsif @link_text.present?
-
1
@link_text = old_name.to_name.sub_in(@link_text, with: new_name)
-
end
-
end
-
-
1
def explicit_link?
-
244
@explicit_link
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
# require File.expand_path("../reference", __FILE__)
-
-
1
class Card
-
1
class Content
-
1
module Chunk
-
# Handler for nest chunks: {{example}}
-
1
class Nest < Reference
-
1
attr_reader :options
-
1
DEFAULT_OPTION = :view # a value without a key is interpreted as view
-
-
1
Chunk.register_class(self, prefix_re: '\\{\\{',
-
full_re: /\A\{\{([^\{\}]*)\}\}/,
-
idx_char: "{")
-
-
1
def interpret match, _content
-
3187
in_brackets = strip_tags match[1]
-
3187
name, @opt_lists = in_brackets.split "|", 2
-
3187
name = name.to_s.strip
-
3187
if name =~ /^\#/
-
4
@process_chunk = name =~ /^\#\#/ ? "" : visible_comment(in_brackets)
-
else
-
3183
@options = interpret_options.merge nest_name: name,
-
nest_syntax: in_brackets
-
3183
@name = name
-
end
-
end
-
-
1
def strip_tags string
-
# note: not using ActionView's strip_tags here
-
# because this needs to be super fast.
-
3187
string.gsub(/\<[^\>]*\>/, "")
-
end
-
-
1
def visible_comment message
-
2
"<!-- #{CGI.escapeHTML message} -->"
-
end
-
-
1
def interpret_options
-
3183
raw_options = @opt_lists.to_s.split("|").reverse
-
3183
raw_options.inject(nil) do |prev_level, level_options|
-
2857
interpret_piped_options level_options, prev_level
-
end || {}
-
end
-
-
1
def interpret_piped_options list_string, items
-
2857
options_hash = items.nil? ? {} : { items: items }
-
2857
option_string_to_hash list_string, options_hash
-
2857
options_hash
-
end
-
-
1
def option_string_to_hash list_string, options_hash
-
2857
each_option(list_string) do |key, value|
-
2944
key = key.to_sym
-
2944
if key == :item
-
3
options_hash[:items] ||= {}
-
3
options_hash[:items][:view] = value
-
2941
elsif Card::View::Options.shark_keys.include? key
-
2929
options_hash[key] = value
-
# else
-
# handle other keys
-
end
-
end
-
end
-
-
1
def inspect
-
"<##{self.class}:n[#{@name}] p[#{@process_chunk}] txt:#{@text}>"
-
end
-
-
1
def process_chunk
-
1908
return @process_chunk if @process_chunk
-
-
1905
referee_name
-
1905
@processed = format.content_nest(@options)
-
# this is not necessarily text, sometimes objects for json
-
end
-
-
1
def replace_reference old_name, new_name
-
89
replace_name_reference old_name, new_name
-
89
nest_body = [@name.to_s, @opt_lists].compact * "|"
-
89
@text = "{{#{nest_body}}}"
-
end
-
-
1
def explicit_view= view
-
return if @options[:view]
-
# could check to make sure it's not already the default...
-
if @text =~ /\|/
-
@text.sub! "|", "|#{view};"
-
else
-
@text.sub! "}}", "|#{view}}}"
-
end
-
end
-
-
1
def main?
-
17
nest_name == "_main"
-
end
-
-
1
def nest_name
-
17
options&.dig :nest_name
-
end
-
-
1
def self.gsub string
-
22
string.gsub(/\{\{([^\}]*)\}\}/) do |_match|
-
21
yield(Regexp.last_match[1])
-
end
-
end
-
-
1
def raw_options
-
6
@opt_lists
-
end
-
-
1
private
-
-
1
def each_option attr_string
-
2861
return if attr_string.blank?
-
2858
attr_string.strip.split(";").each do |pair|
-
# key is optional for view option
-
2948
value, key = pair.split(":", 2).reverse
-
2948
key ||= self.class::DEFAULT_OPTION.to_s
-
2948
yield key.strip, value.strip
-
end
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
class Content
-
1
module Chunk
-
# This should find +Alfred+ in expressions like
-
# 1) {"name":"Alfred"}
-
# 2a) {"name":["in","Alfred"]}
-
# 3a) {"plus_right":["Alfred"]}
-
# but not in
-
# 2b) "content":"foo", "Alfred":"bar"
-
# 3b) {"name":["Alfred", "Toni"]} ("Alfred" is an operator here)
-
# It's not possible to distinguish between 2a) and 2b) or 3a) and 3b) with a
-
# simple regex, hence we use a too general regex and check for query keywords
-
# after the match, which of course means that we don't find references with
-
# query keywords as name
-
-
1
require File.expand_path("reference", __dir__)
-
1
class QueryReference < Reference
-
1
QUERY_KEYWORDS = ::Set.new(
-
(
-
1
::Card::Query::MODIFIERS.keys +
-
::Card::Query::OPERATORS.keys +
-
::Card::Query::ATTRIBUTES.keys +
-
::Card::Query::CONJUNCTIONS.keys +
-
%w[desc asc count]
-
).map(&:to_s)
-
)
-
-
1
Card::Content::Chunk.register_class(
-
self, prefix_re: '(?<=[:,\\[])\\s*"',
-
# we check for colon, comma or square bracket before a quote
-
# we have to use a lookbehind, otherwise
-
# if the colon matches it would be
-
# identified mistakenly as an URI chunk
-
full_re: /\A\s*"([^"]+)"/,
-
idx_char: '"'
-
)
-
-
# OPTIMIZE: instead of comma or square bracket check for operator followed
-
# by comma or "plus_right"|"plus_left"|"plus" followed by square bracket
-
# something like
-
# prefix_patterns = [
-
# "\"\\s*(?:#{Card::Query::OPERATORS.keys.join('|')})\"\\s*,",
-
# "\"\\s*(?:#{Card::Query::PLUS_ATTRIBUTES}.keys
-
# .join('|')})\\s*:\\s*\\[\\s*",
-
# "\"\\s*(?:#{(QUERY_KEYWORDS - Card::Query::PLUS_ATTRIBUTES)
-
# .join('|')})\"\\s*:",
-
# ]
-
# prefix_re: '(?<=#{prefix_patterns.join('|')})\\s*"'
-
# But: What do we do with the "in" operator? After the first value there is
-
# no prefix which we can use to detect the following values as
-
# QueryReference chunks
-
-
1
class << self
-
1
def full_match content, prefix
-
# matches cardnames that are not keywords
-
# FIXME: would not match cardnames that are keywords
-
338
match, offset = super(content, prefix)
-
338
return if !match || keyword?(match[1])
-
-
313
[match, offset]
-
end
-
-
1
def keyword? str
-
338
return unless str
-
-
338
QUERY_KEYWORDS.include?(str.tr(" ", "_").downcase)
-
end
-
end
-
-
1
def interpret match, _content
-
313
@name = match[1]
-
end
-
-
1
def process_chunk
-
4
@process_chunk ||= @text
-
end
-
-
1
def inspect
-
"<##{self.class}:n[#{@name}] p[#{@process_chunk}] txt:#{@text}>"
-
end
-
-
1
def replace_reference old_name, new_name
-
2
replace_name_reference old_name, new_name
-
2
@text = "\"#{@name}\""
-
end
-
-
1
def reference_code
-
293
"Q" # for "Query"
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
class Card
-
1
class Content
-
1
module Chunk
-
1
class Reference < Abstract
-
1
attr_accessor :referee_name, :name
-
-
1
def referee_name
-
5826
return if name.nil?
-
5532
@referee_name ||= referee_name_from_rendered(render_obj(name))
-
5532
@referee_name = @referee_name.absolute(card.name).to_name
-
rescue Card::Error::NotFound
-
# do not break on missing id/codename references.
-
end
-
-
1
def referee_name_from_rendered rendered_name
-
5408
ref_card = fetch_referee_card rendered_name
-
5408
ref_card ? ref_card.name : rendered_name.to_name
-
end
-
-
1
def referee_card
-
11
@referee_card ||= referee_name && Card.fetch(referee_name)
-
end
-
-
1
def replace_name_reference old_name, new_name
-
179
@referee_card = nil
-
179
@referee_name = nil
-
179
if name.is_a? Card::Content
-
name.find_chunks(Chunk::Reference).each do |chunk|
-
chunk.replace_reference old_name, new_name
-
end
-
else
-
179
@name = name.to_name.swap old_name, new_name
-
end
-
end
-
-
1
def render_obj raw
-
6516
if format && raw.is_a?(Card::Content)
-
2
format.process_content raw
-
else
-
6514
raw
-
end
-
end
-
-
1
private
-
-
1
def fetch_referee_card rendered_name
-
5408
case rendered_name # FIXME: this should be standard fetch option.
-
when /^\~(\d+)$/ # get by id
-
Card.fetch Regexp.last_match(1).to_i
-
when /^\:(\w+)$/ # get by codename
-
143
Card.fetch Regexp.last_match(1).to_sym
-
end
-
end
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
-
1
require "uri"
-
-
# This wiki chunk matches arbitrary URIs, using patterns from the Ruby URI
-
# modules.
-
# It parses out a variety of fields that could be used by formats to format
-
# the links in various ways (shortening domain names, hiding email addresses)
-
# It matches email addresses and host.com.au domains without schemes (http://)
-
# but adds these on as required.
-
#
-
# The heuristic used to match a URI is designed to err on the side of caution.
-
# That is, it is more likely to not autolink a URI than it is to accidently
-
# autolink something that is not a URI. The reason behind this is it is easier
-
# to force a URI link by prefixing 'http://' to it than it is to escape and
-
# incorrectly marked up non-URI.
-
#
-
# I'm using a part of the [ISO 3166-1 Standard][iso3166] for country name
-
# suffixes.
-
# The generic names are from www.bnoack.com/data/countrycode2.html)
-
# [iso3166]: http://geotags.com/iso3166/
-
1
module Card::Content::Chunk
-
1
class URI < Abstract
-
1
SCHEMES = %w[irc http https ftp ssh git sftp file ldap ldaps mailto].freeze
-
-
6
REJECTED_PREFIX_RE = %w{! ": " ' ](}.map { |s| Regexp.escape s } * "|"
-
-
1
attr_reader :uri, :link_text
-
1
delegate :to, :scheme, :host, :port, :path, :query, :fragment, to: :uri
-
-
1
Card::Content::Chunk.register_class(
-
self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})(?:#{SCHEMES * '|'})\\:)",
-
full_re: /\A#{::URI.regexp(SCHEMES)}/,
-
idx_char: ":"
-
)
-
-
1
class << self
-
1
def full_match content, prefix
-
213
prepend_str = if prefix[-1, 1] != ":" && config[:prepend_str]
-
140
config[:prepend_str]
-
else
-
73
""
-
end
-
213
content = prepend_str + content
-
213
match = super content, prefix
-
213
[match, prepend_str.length]
-
end
-
-
1
def context_ok? content, chunk_start
-
213
preceding_string = content[chunk_start - 2..chunk_start - 1]
-
213
preceding_string !~ /(?:#{REJECTED_PREFIX_RE})$/
-
end
-
end
-
-
1
def interpret match, _content
-
207
chunk = match[0]
-
207
last_char = chunk[-1, 1]
-
207
chunk.gsub!(/(?: )+/, "")
-
-
@trailing_punctuation =
-
207
if %w[, . ) ! ? :].member?(last_char)
-
6
@text.chop!
-
6
chunk.chop!
-
6
last_char
-
end
-
207
chunk.sub!(/\.$/, "")
-
-
207
@link_text = chunk
-
207
@uri = ::URI.parse(chunk)
-
207
@process_chunk = process_uri_chunk
-
rescue ::URI::Error => e
-
# warn "rescue parse #{chunk_class}:
-
# '#{m}' #{e.inspect} #{e.backtrace*"\n"}"
-
Rails.logger.warn "rescue parse #{self.class}: #{e.inspect}"
-
end
-
-
1
private
-
-
1
def process_text
-
67
@link_text
-
end
-
-
1
def process_uri_chunk
-
207
link = format.link_to_resource @link_text, process_text
-
207
"#{link}#{@trailing_punctuation}"
-
end
-
end
-
-
# FIXME: DRY, merge these two into one class
-
1
class EmailURI < URI
-
1
PREPEND_STR = "mailto:".freeze
-
1
EMAIL = '[a-zA-Z\\d](?:[-a-zA-Z\\d.]*[a-zA-Z\\d])?\\@'.freeze
-
-
1
Card::Content::Chunk.register_class(
-
self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})#{EMAIL})\\b",
-
full_re: /\A#{::URI.regexp(SCHEMES)}/,
-
prepend_str: PREPEND_STR,
-
idx_char: "@"
-
)
-
-
# removes the prepended string from the unchanged match text
-
1
def process_text
-
44
@text = @text.sub(/^mailto:/, "")
-
end
-
end
-
-
1
class HostURI < URI
-
GENERIC = "aero|biz|com|coop|edu|gov|info|int|mil|" \
-
1
"museum|name|net|org".freeze
-
-
COUNTRY = "ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|" \
-
"bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cf|cd|cg|" \
-
"ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|" \
-
"ec|ee|eg|eh|er|es|et|fi|fj|fk|fm|fo|fr|fx|ga|gb|gd|ge|gf|gh|" \
-
"gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|" \
-
"il|in|io|iq|ir|is|it|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|" \
-
"kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|" \
-
"mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|" \
-
"no|np|nr|nt|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pt|pw|py|" \
-
"qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|" \
-
"st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tp|tr|tt|tv|tw|" \
-
"tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|" \
-
"za|zm|zr|zw|" \
-
1
"eu".freeze # made this separate, since it's not technically
-
# a country -efm
-
# These are needed otherwise HOST will match almost anything
-
-
1
TLDS = "(?:#{GENERIC}|#{COUNTRY})".freeze
-
# TLDS = "(?:#{GENERIC})"
-
-
1
PREPEND_STR = "http://".freeze
-
1
HOST = "(?:[a-zA-Z\\d](?:[-a-zA-Z\\d]*[a-zA-Z\\d])?\\.)+#{TLDS}".freeze
-
-
1
Card::Content::Chunk.register_class(
-
self, prefix_re: "(?:(?!#{REJECTED_PREFIX_RE})#{HOST})\\b",
-
full_re: /\A#{::URI.regexp(SCHEMES)}/,
-
prepend_str: PREPEND_STR
-
)
-
-
# removes the prepended string from the unchanged match text
-
1
def process_text
-
96
@text = @text.sub(%r{^http://}, "")
-
end
-
end
-
end
-
1
class Card
-
1
class Content
-
1
module Chunk
-
1
class ViewStub < Abstract
-
1
Chunk.register_class(
-
self,
-
prefix_re: Regexp.escape("(StUb"),
-
full_re: /\A\(StUb(.*?)sTuB\)/m,
-
idx_char: "("
-
)
-
-
1
def initialize text, content
-
super
-
end
-
-
1
def interpret match, _content
-
@stub_hash = initial_stub_hash match[1]
-
interpret_hash_values
-
end
-
-
1
def initial_stub_hash string
-
JSON.parse(string).symbolize_keys
-
# MessagePack.unpack(hex_to_bin(string)).symbolize_keys
-
end
-
-
1
def hex_to_bin string
-
string.scan(/../).map { |x| x.hex.chr }.join
-
end
-
-
1
def interpret_hash_values
-
@stub_hash.keys.each do |key|
-
send "interpret_#{key}"
-
end
-
end
-
-
1
def interpret_cast
-
@stub_hash[:cast].symbolize_keys!
-
end
-
-
1
def interpret_view_opts
-
@stub_hash[:view_opts].symbolize_keys!
-
end
-
-
1
def interpret_format_opts
-
hash = @stub_hash[:format_opts]
-
hash.symbolize_keys!
-
hash[:nest_mode] = hash[:nest_mode].to_sym
-
hash[:override] = hash[:override] == "true"
-
hash[:context_names].map!(&:to_name)
-
end
-
-
1
def process_chunk
-
@processed = format.stub_nest @stub_hash
-
end
-
-
1
def result
-
@processed
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Rule
-
1
class PreferenceCache < Cache
-
1
self.sql = %(
-
SELECT
-
preferences.id AS rule_id,
-
settings.id AS setting_id,
-
sets.id AS set_id,
-
sets.left_id AS anchor_id,
-
sets.right_id AS set_tag_id,
-
users.id AS user_id
-
FROM cards preferences
-
JOIN cards user_sets ON preferences.left_id = user_sets.id
-
JOIN cards settings ON preferences.right_id = settings.id
-
JOIN cards users ON user_sets.right_id = users.id
-
JOIN cards sets ON user_sets.left_id = sets.id
-
WHERE sets.type_id = #{SetID}
-
AND settings.type_id = #{SettingID}
-
AND (users.type_id = #{UserID} or users.codename = 'all')
-
AND sets.trash is false
-
AND settings.trash is false
-
AND users.trash is false
-
AND user_sets.trash is false
-
AND preferences.trash is false;
-
).freeze
-
-
1
self.cache_key = "PREFERENCES".freeze
-
1
USER_ID_CACHE_KEY = "USER_IDS".freeze
-
-
1
class << self
-
1
def user_ids
-
600
Card.cache.read(USER_ID_CACHE_KEY) || (populate && user_ids)
-
end
-
-
1
def populate
-
83
@rows = nil
-
83
super.tap do
-
83
populate_user_ids
-
83
@rows = nil
-
end
-
end
-
-
1
def populate_user_ids
-
83
Card.cache.write USER_ID_CACHE_KEY, user_id_hash
-
end
-
-
1
def user_id_hash
-
83
rows.each_with_object({}) do |row, hash|
-
1270
key = lookup_key_without_user row
-
1270
hash[key] ||= []
-
1270
hash[key] << row["user_id"]
-
end
-
end
-
-
1
def clear
-
304
super
-
304
Card.cache.write USER_ID_CACHE_KEY, nil
-
end
-
-
1
def rows
-
166
@rows ||= super
-
end
-
-
1
alias :lookup_key_without_user :lookup_key
-
-
1
def lookup_key row
-
1270
return unless (base = lookup_key_without_user row)
-
-
1270
"#{base}+#{row['user_id']}"
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
module Rule
-
1
class ReadRuleCache < Cache
-
1
self.sql = %(
-
SELECT
-
refs.referee_id AS party_id,
-
read_rules.id AS read_rule_id
-
FROM cards read_rules
-
JOIN card_references refs ON refs.referer_id = read_rules.id
-
JOIN cards sets ON read_rules.left_id = sets.id
-
WHERE read_rules.right_id = #{ReadID}
-
AND sets.type_id = #{SetID}
-
AND read_rules.trash is false
-
AND sets.trash is false;
-
).freeze
-
-
1
self.cache_key = "READRULES".freeze
-
-
1
class << self
-
1
def lookup_hash
-
58
rows.each_with_object({}) do |row, h|
-
1641
party_id = row["party_id"].to_i
-
1641
h[party_id] ||= []
-
1641
h[party_id] << row["read_rule_id"].to_i
-
end
-
end
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Layout
-
# Layout based on a card's content
-
1
class CardLayout < Layout
-
1
def layout_card
-
46
@layout_card ||= Card.quick_fetch @layout
-
end
-
-
1
def render
-
36
@format.process_content layout_card.content, chunk_list: :references
-
end
-
-
1
def fetch_main_nest_opts
-
10
main_nest = find_main_nest_chunk
-
# don't .& me !! (can be false)
-
10
(main_nest && main_nest.options) ||
-
raise(Card::Error, "no main nest found in layout \"#{@layout}\"")
-
end
-
-
1
MAIN_NESTING_LIMIT = 5
-
-
1
def find_main_nest_chunk card=layout_card, depth=0
-
11
content = Card::Content.new(card.content, @format, chunk_list: :nest_only)
-
11
return false unless content.each_chunk.count.positive?
-
-
11
main_chunk(content) || go_deeper(content, depth)
-
end
-
-
1
def go_deeper content, depth
-
1
return false if depth > MAIN_NESTING_LIMIT
-
-
1
content.each_chunk do |chunk|
-
1
main_chunk = find_main_nest_chunk chunk.referee_card, depth + 1
-
1
return main_chunk if main_chunk
-
end
-
false
-
end
-
-
1
def main_chunk content
-
11
content.each_chunk.find(&:main?)
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Layout
-
1
class CodeLayout < Layout
-
1
def render
-
@format.send Card::Set::Format.layout_method_name(@layout)
-
end
-
end
-
end
-
end
-
1
class Card
-
1
class Layout
-
1
class UnknownLayout < Layout
-
1
SCOPE = "mod.core.format.html_format".freeze
-
-
1
def render
-
@format.output [header, text]
-
end
-
-
1
def header
-
@format.content_tag(:h1, @format.tr(:unknown_layout, scope: SCOPE, name: @layout))
-
end
-
-
1
def text
-
@format.tr(:available_layouts, scope: SCOPE,
-
available_layouts: self.class.built_in_layouts)
-
end
-
end
-
end
-
end
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (BsBadge)
-
#
-
1
module BsBadge;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/bs_badge.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def labeled_badge count, label, opts={}
-
haml :labeled_badge, badge_haml_opts(count, label, opts)
-
end
-
-
1
def tab_badge count, label, opts={}
-
haml :tab_badge, badge_haml_opts(count, label, opts)
-
end
-
-
1
def badge_haml_opts count, label, opts
-
process_badge_opts count, opts
-
{ count: count, label: label, klass: opts[:klass], color: opts[:color],
-
title: opts[:title] }
-
end
-
-
1
def process_badge_opts count, opts
-
if count.try(:zero?) && !opts[:zero_ok]
-
opts[:klass] = [opts[:klass], "disabled-o"].compact.join " "
-
end
-
opts[:color] ||= "secondary"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/bs_badge.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Filterable)
-
#
-
1
module Filterable;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/filterable.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def filterable filter_hash={}, html_opts={}
-
add_class html_opts, "_filterable _noFilterUrlUpdates"
-
html_opts[:data] ||= {}
-
html_opts[:data][:filter] = filter_hash
-
wrap_with :div, yield, html_opts
-
end
-
-
1
def filtering selector=nil
-
selector ||= "._filter-widget:visible"
-
wrap_with :div, yield, class: "_filtering", "data-filter-selector": selector
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/filterable.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (FilterableBar)
-
#
-
1
module FilterableBar;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/filterable_bar.rb"; end
-
1
include_set Abstract::Filterable
-
-
1
before :bar do
-
class_up "bar-body", "_filterable"
-
super()
-
end
-
-
1
before :expanded_bar do
-
class_up "bar", "_filterable"
-
super()
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/filterable_bar.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Utility)
-
#
-
1
module Utility;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/utility.rb"; end
-
-
1
def fetch_params params
-
Env.params.select { |key, val| val && params.include?(key) }
-
.with_indifferent_access
-
end
-
-
1
def param_to_i key, default
-
if (value = Env.params[key])
-
value.to_i
-
else
-
default
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/utility/set/abstract/utility.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Admin"
-
#
-
# collect arrays of the form
-
1
module Admin;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/admin.rb"; end
-
# [task symbol, { execute_policy: block, stats_policy: block }]
-
1
basket :tasks
-
-
1
def run_task_from_task_basket task
-
task = task.to_sym
-
task_data = tasks.find {|h| h[:name].to_sym == task.to_sym}
-
if !irreversibles_tasks_allowed? && task_data[:irreversible]
-
not_allowed task_data[:stats][:link_text]
-
else
-
task_data[:execute_policy].call if task_data
-
end
-
end
-
-
1
event :admin_tasks, :initialize, on: :update do
-
return unless (task = Env.params[:task])
-
raise Card::Error::PermissionDenied, self unless Auth.always_ok?
-
case task.to_sym
-
when :clear_cache then Card::Cache.reset_all
-
when :repair_references then Card::Reference.repair_all
-
when :repair_permissions then Card.repair_all_permissions
-
when :clear_solid_cache then Card.clear_solid_cache
-
when :clear_machine_cache then Card.reset_all_machines
-
when :clear_script_cache then Card.reset_script_machine
-
when :clear_history
-
not_allowed "clear history" unless irreversibles_tasks_allowed?
-
Card::Action.delete_old
-
else
-
run_task_from_task_basket task
-
end
-
abort :success
-
end
-
-
1
def not_allowed task
-
raise Card::Error::PermissionDenied,
-
"The admin task '#{task}' is disabled for security reasons.<br>"\
-
"You can enable it with the config option 'allow_irreversible_admin_tasks'"
-
end
-
-
1
def irreversibles_tasks_allowed?
-
Cardio.config.allow_irreversible_admin_tasks
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core, cache: :never do
-
stats = card_stats
-
stats += cache_stats
-
stats += memory_stats
-
card.tasks.each do |task|
-
stats += Array.wrap task[:stats]
-
end
-
table_content = stats.map { |args| stat_row(args) }
-
table table_content, header: %w[Stat Value Action]
-
end
-
-
1
def card_stats
-
[
-
{ title: "cards",
-
count: Card.where(trash: false) },
-
{ title: "actions",
-
count: Card::Action },
-
# link_text: "clear history",
-
# task: "clear_history" },
-
{ title: "references",
-
count: Card::Reference }
-
# link_text: "repair all",
-
# task: "repair_references" }
-
]
-
end
-
-
1
def cache_stats
-
[
-
{ title: "solid cache",
-
count: solid_cache_count, unit: " cards",
-
link_text: "clear solid cache",
-
task: "clear_solid_cache" },
-
{ title: "machine cache",
-
count: machine_cache_count, unit: " cards",
-
link_text: "clear machine cache",
-
task: "clear_machine_cache" }
-
]
-
# return stats unless Card.config.view_cache#
-
# stats << { title: "view cache",
-
# count: Card::View,
-
# link_text: "clear view cache",
-
# task: "clear_view_cache" }
-
end
-
-
1
def memory_stats
-
oldmem = session[:memory]
-
session[:memory] = newmem = card.profile_memory
-
stats = [
-
{ title: "memory now",
-
count: newmem, unit: "M",
-
link_text: "clear cache", task: "clear_cache" }
-
]
-
return stats unless oldmem
-
stats << { title: "memory prev", count: oldmem, unit: "M" }
-
stats << { title: "memory diff", count: newmem - oldmem, unit: "M" }
-
stats
-
end
-
-
1
def stat_row args={}
-
res = [(args[:title] || "")]
-
res << "#{count(args[:count])}#{args[:unit]}"
-
return res unless args[:task]
-
res << link_to_card(:admin, (args[:link_text] || args[:task]),
-
path: { action: :update, task: args[:task] })
-
res
-
end
-
-
1
def count counter
-
counter = counter.call if counter.is_a?(Proc)
-
counter.respond_to?(:count) ? counter.count : counter
-
end
-
-
1
def solid_cache_count
-
Card.search right: { codename: "solid_cache" }, return: "count"
-
end
-
-
1
def machine_cache_count
-
Card::Virtual.where(right_id: MachineCacheID).count
-
end
-
-
1
def delete_sessions_link months
-
link_to_card :admin, months, path: { action: :update, months: months,
-
task: "delete_old_sessions" }
-
end
-
end
-
-
1
def current_memory_usage
-
`ps -o rss= -p #{Process.pid}`.to_i
-
end
-
-
1
def profile_memory &block
-
before = current_memory_usage
-
if block_given?
-
instance_eval(&block)
-
else
-
before = 0
-
end
-
(current_memory_usage - before) / 1024.to_i
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/admin.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "AdminInfo"
-
#
-
1
module AdminInfo;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/admin_info.rb"; end
-
1
basket :warnings
-
-
# For each warning in the basket (eg :my_warning), the core view
-
# will run a test by appending a question mark (eg #my_warning?).
-
# If it fails it will generate a message by appending message
-
# (eg #my_warning_message).
-
-
1
add_to_basket :warnings, :no_email_delivery
-
-
1
def no_email_delivery?
-
Card.config.action_mailer.perform_deliveries == false
-
end
-
-
1
def clean_html?
-
false
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
warnings = card.warnings.map do |warning|
-
card.send("#{warning}?") ? send("#{warning}_message") : nil
-
end
-
warnings.compact!
-
warnings.empty? ? "" : warning_alert(warnings)
-
end
-
-
1
def warning_alert warnings
-
admin_warn = I18n.t(:admin_warn, scope: "mod.admin.set.self.admin_info")
-
# 'ADMINISTRATOR WARNING'
-
alert :warning, true do
-
"<h5>#{admin_warn}</h5>" + list_tag(warnings)
-
end
-
end
-
-
1
def no_email_delivery_message
-
# "Email delivery is turned off."
-
# "Change settings in config/application.rb to send sign up notifications."
-
I18n.t(:email_off,
-
scope: "mod.admin.set.self.admin_info",
-
path: "config/application.rb")
-
end
-
-
1
def warning_list_with_auto_scope warnings
-
# 'ADMINISTRATOR WARNING'
-
admin_warn = tr(:admin_warn)
-
"<h5>#{admin_warn}</h5>" + warnings.join("\n")
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/admin_info.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Debugger"
-
#
-
1
module Debugger;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/debugger.rb"; end
-
1
def raw_help_text
-
"show more useful error pages"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/debugger.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Trash"
-
#
-
1
module Trash;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/trash.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
rows = trashed_cards.map { |tc| trash_table_row(tc) }
-
output [
-
restored,
-
(empty_trash_link if rows.present?),
-
table(rows, header: ["card", "deleted", "by", ""])
-
]
-
end
-
-
1
def trashed_cards
-
Card.where(trash: true).order(updated_at: :desc)
-
end
-
-
1
def trash_table_row card
-
[
-
card.name,
-
"#{time_ago_in_words(card.updated_at)} ago",
-
Card[card.updater_id].name,
-
"#{history_link(card)} | #{restore_link(card)}"
-
]
-
end
-
-
1
def restored
-
return unless (res_id = Env.params[:restore]) &&
-
(res_card = Card[res_id.to_i])
-
alert :success, true do
-
wrap_with(:h5, "restored") + subformat(res_card).render_bar
-
end
-
end
-
-
1
def empty_trash_link
-
wrap_with(
-
:p,
-
button_link("empty trash",
-
btn_type: :default,
-
path: { mark: :admin, action: :update, task: :empty_trash,
-
success: { id: "~#{card.id}" } },
-
"data-confirm" => "Are you sure you want to delete "\
-
"all cards in the trash?")
-
)
-
end
-
-
1
def history_link trashed_card
-
link_to_card trashed_card, "history",
-
path: { view: :history, look_in_trash: true }
-
end
-
-
1
def restore_link trashed_card
-
before_delete = trashed_card.actions[-2]
-
link_to "restore", method: :post,
-
rel: "nofollow",
-
remote: true,
-
class: "slotter",
-
path: { id: trashed_card.id,
-
view: :open,
-
look_in_trash: true,
-
action: :update,
-
restore: trashed_card.id,
-
action_ids: [before_delete],
-
success: { id: "~#{card.id}" } }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/trash.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Version"
-
#
-
# -*- encoding : utf-8 -*-
-
-
1
module Version;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/version.rb"; end
-
# require "card/version"
-
-
1
def ok_to_read
-
23
true
-
end
-
-
1
def content
-
23
Card::Version.release
-
end
-
-
# view :core, :raw
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/admin/set/self/version.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (CodeFile)
-
#
-
1
module CodeFile;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/code_file.rb"; end
-
1
def self.included host_class
-
34
host_class.mattr_accessor :file_content_mod_name
-
34
host_class.file_content_mod_name = Card::Set.mod_name(caller)
-
end
-
-
# FIXME: these should abstracted and configured on the types
-
# (same codes for `rake card:create:codefile`)
-
-
# @return [Array<String>, String] the name of file(s) to be loaded
-
1
def source_files
-
12
case type_id
-
when CoffeeScriptID then "#{codename}.js.coffee"
-
when JavaScriptID then "#{codename}.js"
-
6
when CssID then "#{codename}.css"
-
6
when ScssID then "#{codename}.scss"
-
end
-
end
-
-
1
def source_dir
-
14
case type_id
-
when CoffeeScriptID, JavaScriptID then "lib/javascript"
-
14
when CssID, ScssID then "lib/stylesheets"
-
else
-
"lib"
-
end
-
end
-
-
1
def find_file filename
-
22
modname = file_content_mod_name
-
22
modname = $1 if modname =~ /^card-mod-(\w*)/
-
22
mod_path = Card::Mod.dirs.path modname
-
22
file_path = File.join(mod_path, source_dir, filename)
-
22
unless File.exist?(file_path)
-
Rails.logger.info "couldn't locate file #{filename} at #{file_path}"
-
return nil
-
end
-
22
file_path
-
end
-
-
1
def existing_source_paths
-
9
Array.wrap(source_files).map do |filename|
-
11
find_file(filename)
-
end.compact
-
end
-
-
1
def source_changed? since:
-
2
existing_source_paths.any? { |path| ::File.mtime(path) > since }
-
end
-
-
1
def content
-
9
Array.wrap(source_files).map do |filename|
-
11
if (source_path = find_file filename)
-
11
Rails.logger.info "reading file: #{source_path}"
-
11
File.read source_path
-
end
-
end.compact.join "\n"
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :input do
-
"Content is stored in file and can't be edited."
-
end
-
-
1
view :file_size do
-
"#{card.name}: #{number_to_human_size card.content.bytesize}"
-
end
-
-
1
def short_content
-
fa_icon("exclamation-circle", class: "text-muted pr-2") +
-
wrap_with(:span, "file", class: "text-muted")
-
end
-
-
1
def standard_submit_button
-
multi_card_editor? ? super : ""
-
end
-
end
-
-
1
def coffee_files files
-
files.map { |f| "script_#{f}.js.coffee" }
-
end
-
-
1
def scss_files files
-
4
files.map { |f| "style_#{f}.scss" }
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/code_file.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (HamlFile)
-
#
-
1
module HamlFile;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/haml_file.rb"; end
-
-
1
def self.included host_class
-
host_class.mattr_accessor :template_path
-
host_class.extend Card::Set::Format::HamlPaths
-
host_class.template_path = host_class.haml_template_path
-
end
-
-
1
def content
-
File.read template_path
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :input do
-
"Content is managed by code and cannot be edited"
-
end
-
-
1
def haml_locals
-
{}
-
end
-
-
1
view :core do
-
haml card.content, haml_locals
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/haml_file.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Lock)
-
#
-
1
module Lock;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/lock.rb"; end
-
1
def lock
-
1
was_already_locked = locked?
-
1
return if was_already_locked
-
1
Auth.as_bot do
-
1
lock!
-
1
yield
-
end
-
ensure
-
1
unlock! unless was_already_locked
-
end
-
-
1
def lock_cache_key
-
4
"UPDATE-LOCK:#{key}"
-
end
-
-
1
def locked?
-
2
Card.cache.read lock_cache_key
-
end
-
-
1
def lock!
-
1
Card.cache.write lock_cache_key, true
-
end
-
-
1
def unlock!
-
1
Card.cache.write lock_cache_key, false
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/lock.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (VendorCodeFile)
-
#
-
1
module VendorCodeFile;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/vendor_code_file.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
def self.included host_class
-
1
host_class.mattr_accessor :file_content_mod_name
-
1
host_class.file_content_mod_name = Card::Set.mod_name(caller)
-
end
-
-
1
def source_dir
-
"vendor"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/abstract/vendor_code_file.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Abort)
-
#
-
1
module Abort;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/abort.rb"; end
-
-
# The Card#abort method is for cleanly exiting an action without continuing
-
# to process any further events.
-
#
-
# Three statuses are supported:
-
#
-
# failure: adds an error, returns false on save
-
# success: no error, returns true on save
-
# triumph: similar to success, but if called on a subcard
-
# it causes the entire action to abort (not just the subcard)
-
1
def abort status, msg="action canceled"
-
1
director.abort
-
1
if status == :failure && errors.empty?
-
errors.add :abort, msg
-
1
elsif status.is_a?(Hash) && status[:success]
-
success << status[:success]
-
status = :success
-
end
-
1
raise Card::Error::Abort.new(status, msg)
-
end
-
-
1
def aborting
-
yield
-
errors.any? ? abort(:failure) : abort(:success)
-
end
-
-
1
def abortable
-
1944
yield
-
rescue Card::Error::Abort => e
-
1
handle_abort_error e
-
end
-
-
1
private
-
-
1
def handle_abort_error e
-
1
if e.status == :triumph
-
@supercard ? raise(e) : true
-
1
elsif e.status == :success
-
1
abort_success
-
end
-
end
-
-
1
def abort_success
-
1
if @supercard
-
@supercard.subcards.delete key
-
@supercard.director.subdirectors.delete self
-
expire :soft
-
end
-
1
true
-
end
-
-
# this is an override of standard rails behavior that rescues abort
-
# makes it so that :success abortions do not rollback
-
1
def with_transaction_returning_status
-
375
status = nil
-
375
self.class.transaction do
-
375
add_to_transaction
-
375
remember_transaction_record_state
-
750
status = abortable { yield }
-
359
raise ActiveRecord::Rollback unless status
-
end
-
359
status
-
end
-
-
# FIXME: these two do not belong here!
-
-
1
public
-
-
1
event :notable_exception_raised do
-
error = Card::Error.current
-
Rails.logger.debug "#{error.message}\n#{error.backtrace * "\n "}"
-
end
-
-
1
def success
-
100
Env.success(name)
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/abort.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Actify)
-
#
-
1
module Actify;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/actify.rb"; end
-
1
def act options={}, &block
-
571
if act_card
-
386
add_to_act options, &block
-
else
-
185
start_new_act &block
-
end
-
end
-
-
1
def act_card
-
1761
Card::Director.act_card
-
end
-
-
1
def act_card?
-
617
self == act_card
-
end
-
-
1
module ClassMethods
-
1
def create! opts
-
62
card = Card.new opts
-
62
card.save!
-
62
card
-
end
-
-
1
def create opts
-
27
card = Card.new opts
-
27
card.save
-
27
card
-
end
-
end
-
-
1
def save! *args
-
289
as_subcard = args.first&.delete :as_subcard
-
578
act(as_subcard: as_subcard) { super }
-
end
-
-
1
def save(*)
-
82
act { super }
-
end
-
-
1
def valid?(*)
-
330
act(validating: true) { super }
-
end
-
-
1
def update *args
-
24
act { super }
-
end
-
-
1
def update! *args
-
66
act { super }
-
end
-
-
1
alias_method :update_attributes, :update
-
1
alias_method :update_attributes!, :update!
-
-
1
private
-
-
1
def start_new_act
-
185
self.director = nil
-
185
Director.run_act(self) do
-
370
run_callbacks(:act) { yield }
-
end
-
end
-
-
1
def add_to_act options={}
-
386
director.appoint self unless @director
-
386
director.head = true unless options[:validating] || options[:as_subcard]
-
386
yield
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/actify.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (ActiveCard)
-
#
-
1
module ActiveCard;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/active_card.rb"; end
-
-
# FIXME: -this needs a better home!
-
1
def format opts={}
-
71
opts = { format: opts.to_sym } if [Symbol, String].member? opts.class
-
71
Card::Format.new self, opts
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/active_card.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (AssignAttributes)
-
#
-
1
module AssignAttributes;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/assign_attributes.rb"; end
-
-
1
def assign_attributes args={}
-
2966
args = prepare_assignment_args args
-
-
2966
assign_with_subcards args do
-
2966
assign_with_set_modules args do
-
2966
params = prepare_assignment_params args
-
2966
super params
-
end
-
end
-
end
-
-
1
def assign_set_specific_attributes
-
4197
set_specific.each_pair do |name, value|
-
6
send "#{name}=", value
-
end
-
end
-
-
1
def extract_subcard_args! args
-
2966
subcards = args.delete("subcards") || args.delete(:subcards) || {}
-
2966
if (subfields = args.delete("subfields") || args.delete(:subfields))
-
3
subfields.each_pair do |key, value|
-
3
subcards[name.field(key)] = value
-
end
-
end
-
2966
args.keys.each do |key|
-
4292
subcards[key] = args.delete(key) if key =~ /^\+/
-
end
-
2966
subcards = subcards.to_unsafe_h if subcards.respond_to?(:to_unsafe_h)
-
2966
subcards
-
end
-
-
1
protected
-
-
1
module ClassMethods
-
1
def assign_or_newish name, attributes, fetch_opts={}
-
95
if (known_card = Card.fetch(name, fetch_opts))
-
11
known_card.refresh.newish attributes
-
11
known_card
-
else
-
84
Card.new attributes.merge(name: name)
-
end
-
end
-
end
-
-
1
def prepare_assignment_params args
-
2966
args = args.to_unsafe_h if args.respond_to?(:to_unsafe_h)
-
2966
params = ActionController::Parameters.new(args)
-
2966
params.permit!
-
2966
params[:db_content] = standardize_content(params[:db_content]) if params[:db_content]
-
2966
params
-
end
-
-
1
def prepare_assignment_args args
-
2966
return {} unless args
-
2966
args = args.stringify_keys
-
2966
normalize_type_attributes args
-
2966
stash_set_specific_attributes args
-
2966
args
-
end
-
-
1
def assign_with_set_modules args
-
2966
set_changed = args["name"] || args["type_id"]
-
2966
return yield unless set_changed
-
-
5842
refresh_set_modules { yield }
-
end
-
-
1
def assign_with_subcards args
-
2966
subcard_args = extract_subcard_args! args
-
2966
yield
-
# name= must come before process subcards
-
2966
return unless subcard_args.present?
-
27
subcards.add subcard_args
-
end
-
-
1
def refresh_set_modules
-
2921
reinclude_set_modules = @set_mods_loaded
-
2921
yield
-
2921
reset_patterns
-
2921
include_set_modules if reinclude_set_modules
-
end
-
-
1
def stash_set_specific_attributes args
-
2966
@set_specific = {}
-
2966
Card.set_specific_attributes.each do |key|
-
26694
set_specific[key] = args.delete(key) if args.key?(key)
-
end
-
end
-
-
1
def normalize_type_attributes args
-
2966
new_type_id = extract_type_id! args unless args.delete("type_lookup") == :skip
-
2966
args["type_id"] = new_type_id if new_type_id
-
end
-
-
1
def extract_type_id! args={}
-
case
-
1817
when (type_id = args.delete("type_id")&.to_i)
-
107
type_id.zero? ? nil : type_id
-
1710
when (type_code = args.delete("type_code")&.to_sym)
-
2
type_id_from_codename type_code
-
1708
when (type_name = args.delete "type")
-
1125
type_id_from_cardname type_name
-
end
-
end
-
-
1
def type_id_from_codename type_code
-
4
type_id_or_error(type_code) { Card::Codename.id type_code }
-
end
-
-
1
def type_id_from_cardname type_name
-
2250
type_id_or_error(type_name) { Card.fetch_id type_name }
-
end
-
-
1
def type_id_or_error val
-
1127
type_id = yield
-
1127
return type_id if type_id
-
-
errors.add :type, "#{val} is not a known type."
-
nil
-
end
-
-
# 'set' refers to the noun not the verb
-
1
def set_specific
-
4410
@set_specific ||= {}
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/assign_attributes.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Cache)
-
#
-
1
module Cache;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/cache.rb"; end
-
1
module ClassMethods
-
1
def retrieve_from_cache cache_key, local_only=false
-
39857
return unless cache
-
39857
local_only ? cache.soft.read(cache_key) : cache.read(cache_key)
-
end
-
-
1
def retrieve_from_cache_by_id id, local_only=false
-
13001
key = Card::Lexicon.name(id)&.key
-
13001
return unless key.present?
-
-
13000
retrieve_from_cache key, local_only if key
-
end
-
-
1
def retrieve_from_cache_by_key key, local_only=false
-
26857
retrieve_from_cache key, local_only
-
end
-
-
1
def write_to_cache card, local_only=false
-
6755
if local_only
-
52
write_to_soft_cache card
-
6703
elsif cache
-
6703
cache.write card.key, card
-
end
-
end
-
-
1
def write_to_soft_cache card
-
508
return unless cache
-
508
cache.soft.write card.key, card
-
end
-
-
1
def expire name
-
24
key = name.to_name.key
-
24
return unless (card = Card.cache.read key)
-
6
card.expire
-
end
-
end
-
-
1
def update_soft_cache
-
Card.write_to_soft_cache self
-
end
-
-
1
def expire_pieces
-
name.piece_names.each do |piece|
-
Card.expire piece
-
end
-
end
-
-
1
def expire cache_type=nil
-
385
return unless (cache_class = cache_class_from_type cache_type)
-
359
expire_views
-
359
expire_names cache_class
-
359
expire_id cache_class
-
end
-
-
1
def cache_class_from_type cache_type
-
385
cache_type ? Card.cache.send(cache_type) : Card.cache
-
end
-
-
1
def view_cache_clean?
-
!db_content_changed?
-
end
-
-
1
def view_cache_keys
-
359
@view_cache_keys ||= hard_read_view_cache_keys || []
-
end
-
-
1
def ensure_view_cache_key cache_key
-
return if view_cache_keys.include? cache_key
-
-
@view_cache_keys << cache_key
-
hard_write_view_cache_keys
-
end
-
-
1
def hard_read_view_cache_keys
-
334
Card.cache.hard&.read_attribute key, :view_cache_keys
-
end
-
-
1
def hard_write_view_cache_keys
-
# puts "WRITE VIEW CACHE KEYS (#{name}): #{view_cache_keys}"
-
Card.cache.hard&.write_attribute key, :view_cache_keys, view_cache_keys
-
end
-
-
1
def expire_views
-
# puts "EXPIRE VIEW CACHE (#{name}): #{view_cache_keys}"
-
359
return unless view_cache_keys.present?
-
Array.wrap(view_cache_keys).each do |view_cache_key|
-
Card::View.cache.delete view_cache_key
-
end
-
@view_cache_keys = []
-
hard_write_view_cache_keys
-
end
-
-
1
def expire_names cache
-
359
[name, name_before_act].uniq.each do |name_version|
-
524
expire_name name_version, cache
-
end
-
end
-
-
1
def expire_name name_version, cache
-
524
return unless name_version.present?
-
422
key_version = name_version.to_name.key
-
422
return unless key_version.present?
-
422
cache.delete key_version
-
end
-
-
1
def expire_id cache
-
359
return unless id.present?
-
349
cache.delete "~#{id}"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/cache.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Chunk)
-
#
-
1
module Chunk;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/chunk.rb"; end
-
-
1
def chunks content, type, named=false
-
content ||= self.content
-
type ||= Card::Content::Chunk
-
all_chunks = Card::Content.new(content, self).find_chunks type
-
named ? all_chunks.select(&:referee_name) : all_chunks
-
end
-
-
1
def reference_chunks content=nil, named=true
-
chunks content, Card::Content::Chunk::Reference, named
-
end
-
-
# named=true rejects commented nests
-
1
def nest_chunks content=nil, named=true
-
chunks content, Card::Content::Chunk::Nest, named
-
end
-
-
# named=true rejects external links (since the don't refer to a card name)
-
1
def link_chunks content=nil, named=false
-
chunks content, Card::Content::Chunk::Link, named
-
end
-
-
1
def each_item_name_with_options content=nil
-
reference_chunks(content).each do |chunk|
-
options = chunk.respond_to?(:options) ? chunk.options : {}
-
yield chunk.referee_name, options
-
end
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def nest_chunks content=nil
-
content ||= _render_raw
-
card.nest_chunks content
-
end
-
-
1
def nested_cards content=nil
-
nest_chunks(content).map(&:referee_card).uniq
-
end
-
-
1
def edit_fields
-
20
voo.edit_structure || []
-
end
-
-
1
def nested_field_names content=nil
-
nest_chunks(content).map(&:referee_name).select { |n| field_name? n }
-
end
-
-
1
def nested_field_cards content=nil
-
nested_cards(content).select { |c| field_name? c.name }
-
end
-
-
1
def field_name? name
-
name.field_of? card.name
-
end
-
-
# @return [Array] of Arrays. each is [nest_name, nest_options_hash]
-
1
def edit_field_configs fields_only=false
-
if edit_fields.present?
-
explicit_edit_fields_config # explicitly configured in voo or code
-
else
-
implicit_edit_fields_config fields_only # inferred from nests
-
end
-
end
-
-
1
def implicit_edit_fields_config fields_only
-
result = []
-
each_nested_chunk(fields: fields_only) do |chunk|
-
result << [chunk.options[:nest_name], chunk.options]
-
end
-
result
-
end
-
-
1
def each_nested_field_chunk &block
-
each_nested_chunk fields: true, &block
-
end
-
-
1
def each_nested_chunk content: nil, fields: false, uniq: true, virtual: true, &block
-
return unless block_given?
-
chunks = prepare_nested_chunks content, fields, uniq
-
process_nested_chunks chunks, virtual, &block
-
end
-
-
1
def uniq_chunks chunks
-
processed = ::Set.new [card.key]
-
chunks.select do |chunk|
-
key = chunk.referee_name.key
-
ok = !processed.include?(key)
-
processed << key
-
ok
-
end
-
end
-
-
1
def field_chunks chunks
-
chunks.select { |chunk| field_name?(chunk.referee_name) }
-
end
-
-
1
private
-
-
1
def prepare_nested_chunks content, fields, uniq
-
chunks = nest_chunks content
-
chunks = field_chunks chunks if fields
-
chunks = uniq_chunks chunks if uniq
-
chunks
-
end
-
-
1
def process_nested_chunks chunks, virtual, &block
-
chunks.each do |chunk|
-
process_nested_chunk chunk, virtual, &block
-
end
-
end
-
-
1
def process_nested_chunk chunk, virtual, &block
-
if chunk.referee_card&.virtual?
-
process_nested_virtual_chunk chunk, &block unless virtual
-
else
-
yield chunk
-
end
-
end
-
-
1
def process_virtual_chunk chunk
-
subformat(chunk.referee_card).each_nested_field_chunk { |sub_chunk| yield sub_chunk }
-
end
-
-
1
def explicit_edit_fields_config
-
edit_fields.map do |cardish, options|
-
field_mark = normalized_edit_field_mark cardish, options
-
options = normalized_edit_field_options options, Card::Name[field_mark]
-
[field_mark, options]
-
end
-
end
-
-
1
def normalized_edit_field_options options, cardname
-
options ||= cardname
-
options.is_a?(String) ? { title: options } : options
-
end
-
-
1
def normalized_edit_field_mark cardish, options
-
return cardish if cardish.is_a?(Card) ||
-
(options.is_a?(Hash) && options.delete(:absolute))
-
card.name.field cardish
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/chunk.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Codename)
-
#
-
1
module Codename;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/codename.rb"; end
-
1
def codename
-
811
super&.to_sym
-
end
-
-
1
event :validate_codename, :validate, on: :update, changed: :codename do
-
validate_codename_permission
-
validate_codename_uniqueness
-
end
-
-
1
event :reset_codename_cache, :integrate, changed: :codename do
-
265
return if action == :create && codename.nil?
-
-
76
Card::Codename.reset_cache
-
76
Card::Codename.generate_id_constants
-
end
-
-
1
private
-
-
1
def validate_codename_permission
-
return if Auth.always_ok? || Auth.as_id == creator_id
-
-
errors.add :codename, tr(:only_admins_codename)
-
end
-
-
1
def validate_codename_uniqueness
-
return (self.codename = nil) if codename.blank?
-
return if errors.present? || !Card.find_by_codename(codename)
-
errors.add :codename, tr(:error_code_in_use, codename: codename)
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/codename.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Collection)
-
#
-
# shared methods for card collections (Pointers, Searches, Sets, etc.)
-
1
module Collection;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/collection.rb"; end
-
1
module ClassMethods
-
1
def search spec, comment=nil
-
461
results = ::Card::Query.run(spec, comment)
-
461
if block_given? && results.is_a?(Array)
-
8
results.each { |result| yield result }
-
end
-
461
results
-
end
-
-
1
def count_by_cql spec
-
7
spec = spec.clone
-
7
spec.delete(:offset)
-
7
search spec.merge(return: "count")
-
end
-
-
1
def find_each options={}
-
# this is a copy from rails (3.2.16) and is needed because this
-
# is performed by a relation (ActiveRecord::Relation)
-
find_in_batches(options) do |records|
-
records.each { |record| yield record }
-
end
-
end
-
-
1
def find_in_batches options={}
-
if block_given?
-
super(options) do |records|
-
yield(records)
-
Card::Cache.reset_soft
-
end
-
else
-
super(options)
-
end
-
end
-
end
-
-
1
def collection?
-
26
item_cards != [self]
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :count do
-
card.item_names.size
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :carousel do
-
bs_carousel unique_id, 0 do
-
nest_item_array.each do |rendered_item|
-
item(rendered_item)
-
end
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/collection.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Content)
-
#
-
1
module Content;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/content.rb"; end
-
1
def content= value
-
57
self.db_content = standardize_content(value)
-
end
-
-
1
def content
-
2609
structured_content || standard_content
-
end
-
1
alias raw_content content #DEPRECATED!
-
-
1
def content?
-
2
content.present?
-
end
-
-
1
def standard_content
-
2785
db_content || (new_card? && template.db_content)
-
end
-
-
1
def standardize_content value
-
143
value.is_a?(Array) ? value.join("\n") : value
-
end
-
-
1
def structured_content
-
2609
structure && template.db_content
-
end
-
-
1
def refresh_content
-
self.content = Card.find(id)&.db_content
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
ONE_LINE_CHARACTER_LIMIT = 60
-
-
1
def chunk_list # override to customize by set
-
295
:default
-
end
-
-
1
view :one_line_content do
-
with_nest_mode :compact do
-
one_line_content
-
end
-
end
-
-
# DEPRECATED
-
1
view :closed_content, :one_line_content
-
-
1
view :raw_one_line_content do
-
raw_one_line_content
-
end
-
-
1
view :label do
-
card.label.to_s
-
end
-
-
1
view :smart_label, cache: :never, unknown: true do
-
label_with_description render_label, label_description
-
end
-
-
1
def label_with_description label, description
-
return label unless description
-
-
"#{label} #{popover_link description}"
-
end
-
-
# TODO: move this into a nest once popovers are stub safe
-
1
def label_description
-
return unless (desc = card.field :description)
-
-
desc.format.render_core
-
end
-
-
1
def raw_one_line_content
-
cut_with_ellipsis render_raw
-
end
-
-
1
def one_line_content
-
Card::Content.smart_truncate render_core
-
end
-
-
1
def cut_with_ellipsis text, limit=one_line_character_limit
-
if text.size <= limit
-
text
-
else
-
text[0..(limit - 3)] + "..."
-
end
-
end
-
-
1
def one_line_character_limit
-
voo.size || ONE_LINE_CHARACTER_LIMIT
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :hidden_content_field, unknown: true, cache: :never do
-
12
hidden_field :content, class: "d0-card-content"
-
end
-
end
-
-
# seems like this should be moved to format so we can fall back on title
-
# rather than name. (In fact, name, title, AND label is a bit much.
-
# Trim to 2?)
-
1
def label
-
name
-
end
-
-
1
def creator
-
Card[creator_id]
-
end
-
-
1
def updater
-
Card[updater_id]
-
end
-
-
1
def save_content_draft _content
-
clear_drafts
-
end
-
-
1
def clear_drafts
-
242
drafts.created_by(Card::Auth.current_id).each(&:delete)
-
end
-
-
1
def last_draft_content
-
drafts.last.card_changes.last.value
-
end
-
-
1
event :set_content, :store, on: :save do
-
242
self.db_content = prepare_db_content
-
242
@selected_action_id = @selected_content = nil
-
242
clear_drafts
-
end
-
-
1
event :save_draft, :store, on: :update, when: :draft? do
-
save_content_draft content
-
abort :success
-
end
-
-
1
event :set_default_content,
-
:prepare_to_validate,
-
on: :create, when: :use_default_content? do
-
15
self.db_content = template.db_content
-
end
-
-
1
def draft?
-
53
Env.params["draft"] == "true"
-
end
-
-
1
def prepare_db_content
-
242
cont = standard_db_content || "" # necessary?
-
242
clean_html? ? Card::Content.clean!(cont) : cont
-
end
-
-
1
def standard_db_content
-
242
if structure
-
# do not override db_content with content from structure
-
16
db_content
-
else
-
226
standard_content
-
end
-
end
-
-
1
def clean_html?
-
242
true
-
end
-
-
1
def use_default_content?
-
196
!db_content_changed? && template && template.db_content.present?
-
end
-
-
1
def unfilled?
-
34
blank_content? && blank_comment? && !subcards?
-
end
-
-
1
def blank_content?
-
34
content.blank? || content.strip.blank?
-
end
-
-
1
def blank_comment?
-
2
comment.blank? || comment.strip.blank?
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/content.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (ContextualContent)
-
#
-
1
module ContextualContent;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/contextual_content.rb"; end
-
1
def context_card
-
2344
@context_card || self
-
end
-
-
1
def with_context context_card
-
6
old_context = @context_card
-
6
@context_card = context_card if context_card
-
6
yield
-
ensure
-
6
@context_card = old_context
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def context_card
-
541
card.context_card
-
end
-
-
1
def with_context context_card
-
6
card.with_context context_card do
-
6
yield
-
end
-
end
-
-
1
def contextual_content context_card, options={}
-
6
view = options.delete(:view) || :core
-
12
with_context(context_card) { render! view, options }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/contextual_content.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Debug)
-
#
-
1
module Debug;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/debug.rb"; end
-
1
def to_s
-
2
"#<#{self.class.name}[#{debug_type}]#{attributes['name']}>"
-
end
-
-
1
def inspect
-
12
tags = []
-
12
tags << "trash" if trash
-
12
tags << "new" if new_card?
-
12
tags << "frozen" if frozen?
-
12
tags << "readonly" if readonly?
-
12
tags << "virtual" if @virtual
-
12
tags << "set_mods_loaded" if @set_mods_loaded
-
-
12
error_messages = errors.any? ? "<E*#{errors.full_messages * ', '}*>" : ""
-
-
12
"#<Card##{id}[#{debug_type}](#{name})#{error_messages}{#{tags * ','}}"
-
end
-
-
1
private
-
-
1
def debug_type
-
14
"#{type_code || ''}:#{type_id}"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/debug.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EventConditions)
-
#
-
1
module EventConditions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/event_conditions.rb"; end
-
1
Card.action_specific_attributes +=
-
%i[skip_hash full_skip_hash trigger_hash full_trigger_hash]
-
-
1
def event_applies? event
-
56250
return unless set_condition_applies? event.set_module, event.opts[:changing]
-
-
17604
Card::Set::Event::CONDITIONS.all? do |key|
-
64349
send "#{key}_condition_applies?", event, event.opts[key]
-
end
-
end
-
-
# force skipping this event for all cards in act
-
1
def skip_event! *events
-
11
@full_skip_hash = nil
-
11
events.each do |event|
-
22
act_skip_hash[event.to_s] = :force
-
end
-
end
-
-
# force skipping this event for this card only
-
1
def skip_event_in_action! *events
-
events.each do |event|
-
full_skip_hash[event.to_s] = :force
-
end
-
end
-
-
# force triggering this event (when it comes up) for all cards in act
-
1
def trigger_event! *events
-
@full_trigger_hash = nil
-
events.each do |event|
-
act_trigger_hash[event.to_s] = :force
-
end
-
end
-
-
# force triggering this event (when it comes up) for this card only
-
1
def trigger_event_in_action! *events
-
events.each do |event|
-
full_trigger_hash[event.to_s] = :force
-
end
-
end
-
-
# hash form of raw skip setting, eg { "my_event" => true }
-
1
def skip_hash
-
387
@skip_hash ||= hash_with_value skip, true
-
end
-
-
1
def trigger_hash
-
@trigger_hash ||= hash_with_value trigger, true
-
end
-
-
1
private
-
-
1
def set_condition_applies? set_module, old_sets
-
56250
return true if set_module == Card
-
-
56250
set_condition_card(old_sets).singleton_class.include? set_module
-
end
-
-
1
def on_condition_applies? _event, actions
-
17604
actions = Array(actions).compact
-
17604
actions.empty? ? true : actions.include?(action)
-
end
-
-
# if changing name/type, the old card has no-longer-applicable set modules, so we create
-
# a new card to determine whether events apply.
-
# (note: cached condition card would ideally be cleared after all
-
# conditions are reviewed)
-
# @param old_sets [True/False] whether to use the old_sets
-
1
def set_condition_card old_sets
-
56250
return self if old_sets || no_current_action?
-
50659
@set_condition_card ||=
-
316
updating_sets? ? set_condition_card_with_new_set_modules : self
-
end
-
-
# existing card is being changed in a way that alters its sets
-
1
def updating_sets?
-
316
action == :update && real? && (type_id_is_changing? || name_is_changing?)
-
end
-
-
# prevents locking in set_condition_card
-
1
def no_current_action?
-
54259
return false if @current_action
-
-
3600
@set_condition_card = nil
-
3600
true
-
end
-
-
1
def set_condition_card_with_new_set_modules
-
22
cc = Card.find id
-
22
cc.name = name
-
22
cc.type_id = type_id
-
22
cc.include_set_modules
-
end
-
-
1
def changed_condition_applies? _event, db_columns
-
19151
return true unless action == :update
-
3813
db_columns = Array(db_columns).compact
-
3813
return true if db_columns.empty?
-
2046
db_columns.any? { |col| single_changed_condition_applies? col }
-
end
-
1
alias_method :changing_condition_applies?, :changed_condition_applies?
-
-
1
def when_condition_applies? _event, block
-
9195
case block
-
19
when Proc then block.call(self)
-
4008
when Symbol then send block
-
5168
else true
-
end
-
end
-
-
# "applies always means event can run
-
# so if skip_condition_applies?, we do NOT skip
-
1
def skip_condition_applies? event, allowed
-
9204
return true unless (val = full_skip_hash[event.name.to_s])
-
-
9
allowed ? val.blank? : (val != :force)
-
end
-
-
1
def trigger_condition_applies? event, required
-
9195
return true unless required
-
-
full_trigger_hash[event.name.to_s].present?
-
end
-
-
1
def single_changed_condition_applies? db_column
-
1075
return true unless db_column
-
1075
send "#{db_column}_is_changing?"
-
end
-
-
1
def wrong_stage opts
-
return false if director.stage_ok? opts
-
if !stage
-
"phase method #{method} called outside of event phases"
-
else
-
"#{opts.inspect} method #{method} called in stage #{stage}"
-
end
-
end
-
-
1
def wrong_action actn
-
return false if on_condition_applies?(nil, actn)
-
"on: #{actn} method #{method} called on #{action}"
-
end
-
-
1
def full_skip_hash
-
9204
@full_skip_hash ||= act_skip_hash.merge skip_in_action_hash
-
end
-
-
1
def act_skip_hash
-
387
(act_card || self).skip_hash
-
end
-
-
1
def skip_in_action_hash
-
365
hash_with_value skip_in_action, true
-
end
-
-
1
def full_trigger_hash
-
@full_trigger_hash ||= act_trigger_hash.merge trigger_in_action_hash
-
end
-
-
1
def trigger_in_action_hash
-
hash_with_value trigger_in_action, true
-
end
-
-
1
def act_trigger_hash
-
(act_card || self).trigger_hash
-
end
-
-
1
def hash_with_value array, value
-
550
Array.wrap(array).each_with_object({}) do |event, hash|
-
hash[event.to_s] = value
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/event_conditions.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Export)
-
#
-
1
module Export;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/export.rb"; end
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
# returns an array of Hashes (each in export_item view)
-
1
view :export, cache: :never do
-
exporting_uniques do
-
Array.wrap(render_export_item).concat(export_items_in_view(:export)).flatten
-
end
-
end
-
-
1
def max_export_depth
-
Env.params[:max_export_depth].present? ? Env.params[:max_export_depth].to_i : 2
-
end
-
-
# returns an array of Hashes (each in export_item view)
-
1
view :export_items, cache: :never do
-
exporting_uniques do
-
export_items_in_view(:export).flatten
-
end
-
end
-
-
# returns Hash with the essentials needed to import a card into a new database
-
1
view :export_item do
-
item = { name: card.name, type: card.type_name, content: card.content }
-
item[:codename] = card.codename if card.codename
-
track_exporting card
-
item
-
end
-
-
1
def export_items_in_view view
-
within_max_depth do
-
valid_items_for_export.map do |item|
-
nest item, view: view
-
end
-
end
-
end
-
-
1
def track_exporting card
-
return unless @exported_keys
-
@exported_keys << card.key
-
end
-
-
1
def exporting_uniques
-
@exported_keys ||= inherit(:exported_keys) || ::Set.new
-
yield
-
end
-
-
# prevent recursion
-
1
def within_max_depth
-
@export_depth ||= inherit(:export_depth).to_i + 1
-
@export_depth > max_export_depth ? [] : yield
-
end
-
-
1
def items_for_export
-
nest_chunks.map do |chunk|
-
next if chunk.try :main?
-
chunk.referee_card
-
end.compact
-
end
-
-
1
def valid_items_for_export
-
items_for_export.flatten.reject(&:blank?).uniq.find_all do |card|
-
valid_export_card? card
-
end
-
end
-
-
1
def valid_export_card? ecard
-
ecard.real? && !@exported_keys.include?(ecard.key)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/export.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Extended)
-
#
-
1
module Extended;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/extended.rb"; end
-
-
1
def extended_item_cards context=nil
-
15
items = item_cards limit: "", context: (context || self).name
-
15
list = []
-
15
book = ::Set.new # avoid loops
-
15
extend_item_list items, list, book until items.empty?
-
15
list
-
end
-
-
1
def extended_item_contents context=nil
-
extended_item_cards(context).map(&:item_names).flatten
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
delegate :extended_item_contents, to: :card
-
end
-
-
1
private
-
-
1
def extend_item_list items, list, book
-
25
item = items.shift
-
25
return if already_extended? item, book
-
25
if item.collection?
-
# keep items in order
-
items.unshift(*item.item_cards)
-
else # no further level of items
-
25
list << item
-
end
-
end
-
-
1
def already_extended? item, book
-
25
return true if book.include? item
-
25
book << item
-
25
false
-
end
-
-
# def extended_list context=nil
-
# context = (context ? context.name : name)
-
# args = { limit: "" }
-
# item_cards(args.merge(context: context)).map do |x|
-
# x.item_cards(args)
-
# end.flatten.map do |x|
-
# x.item_cards(args)
-
# end.flatten.map do |y|
-
# y.item_names(args)
-
# end.flatten
-
# # this could go on and on. more elegant to recurse until you don't have
-
# # a collection
-
# end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/extended.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Fetch)
-
#
-
# = Card#fetch
-
#
-
1
module Fetch;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/fetch.rb"; end
-
# A multipurpose retrieval operator that integrates caching, database lookups,
-
# and "virtual" card construction
-
1
module ClassMethods
-
# Look for cards in
-
# * cache
-
# * database
-
# * virtual cards
-
#
-
# @param args [Integer, String, Card::Name, Symbol, Array]
-
# one or more of the three unique identifiers
-
# 1. a numeric id (Integer)
-
# 2. a name/key (String or Card::Name)
-
# 3. a codename (Symbol)
-
# If you pass more then one mark or an array of marks they get joined with a '+'.
-
# The final argument can be a hash to set the following options
-
# :skip_virtual Real cards only
-
# :skip_modules Don't load Set modules
-
# :look_in_trash Return trashed card objects
-
# :local_only Use only local cache for lookup and storing
-
# new: { opts for Card#new } Return a new card when not found
-
# @return [Card]
-
1
def fetch *args
-
52110
Card::Fetch.new(*args)&.retrieve_or_new
-
rescue ActiveModel::RangeError => _e
-
return Card.new name: "card id out of range: #{f.mark}"
-
end
-
-
# fetch only real (no virtual) cards
-
#
-
# @param mark - see #fetch
-
# @return [Card]
-
1
def [] *mark
-
1979
fetch(*mark, skip_virtual: true)
-
end
-
-
# fetch real cards without set modules loaded. Should only be used for simple attributes
-
# @example
-
# quick_fetch "A", :self, :structure
-
#
-
# @param mark - see #fetch
-
# @return [Card]
-
1
def quick_fetch *mark
-
34186
fetch(*mark, skip_virtual: true, skip_modules: true)
-
end
-
-
# @return [Card]
-
1
def fetch_from_cast cast
-
fetch_args = cast[:id] ? [cast[:id].to_i] : [cast[:name], { new: cast }]
-
fetch *fetch_args
-
end
-
-
#----------------------------------------------------------------------
-
# ATTRIBUTE FETCHING
-
# The following methods optimize fetching of specific attributes
-
-
1
def id cardish
-
9234
case cardish
-
6003
when Integer then cardish
-
83
when Card then cardish.id
-
1
when Symbol then Card::Codename.id cardish
-
3147
else fetch_id cardish
-
end
-
end
-
-
# @param mark_parts - see #fetch
-
# @return [Integer]
-
1
def fetch_id *mark_parts
-
26251
mark = Card::Fetch.new(*mark_parts)&.mark
-
26251
mark.is_a?(Integer) ? mark : quick_fetch(mark.to_s)&.id
-
end
-
-
# @param mark - see #fetch
-
# @return [Card::Name]
-
1
def fetch_name *mark
-
1217
if (card = quick_fetch(*mark))
-
1166
card.name
-
51
elsif block_given?
-
yield.to_name
-
end
-
rescue ActiveModel::RangeError => _e
-
block_given? ? yield.to_name : nil
-
rescue Card::Error::CodenameNotFound => e
-
block_given? ? yield.to_name : raise(e)
-
end
-
-
# @param mark - see #fetch
-
# @return [Integer]
-
1
def fetch_type_id mark
-
25
quick_fetch(mark)&.type_id
-
end
-
end
-
-
#----------------------------------------------------------------------
-
# INSTANCE METHODS
-
# fetching from the context of a card
-
-
1
def fetch traits, opts={}
-
473
opts[:new][:supercard] = self if opts[:new]
-
473
Array.wrap(traits).inject(self) do |card, trait|
-
473
Card.fetch card.name.trait(trait), opts
-
end
-
end
-
-
1
def newish opts
-
22
reset_patterns
-
22
Card.with_normalized_new_args opts do |norm_opts|
-
22
handle_type norm_opts do
-
22
assign_attributes norm_opts
-
22
self.name = name # trigger superize_name
-
end
-
end
-
end
-
-
1
def refresh force=false
-
28
return self unless force || frozen? || readonly?
-
return unless id
-
fresh_card = self.class.find id
-
fresh_card.include_set_modules
-
fresh_card
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/fetch.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (FetchHelper)
-
#
-
1
module FetchHelper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/fetch_helper.rb"; end
-
1
module ClassMethods
-
# a fetch method to support the needs of the card controller.
-
# should be in Decko?
-
1
def controller_fetch args
-
36
card_opts = controller_fetch_opts args
-
36
if args[:action] == "create"
-
# FIXME: we currently need a "new" card to catch duplicates
-
# (otherwise save will just act like a normal update)
-
# We may need a "#create" instance method to handle this checking?
-
9
Card.new card_opts
-
else
-
27
standard_controller_fetch args, card_opts
-
end
-
end
-
-
1
private
-
-
1
def standard_controller_fetch args, card_opts
-
27
mark = args[:mark] || card_opts[:name]
-
27
card = Card.fetch mark, skip_modules: true,
-
look_in_trash: args[:look_in_trash],
-
new: card_opts
-
27
card.assign_attributes card_opts if args[:assign] && card&.real?
-
27
card&.include_set_modules
-
27
card
-
end
-
-
1
def controller_fetch_opts args
-
36
opts = Env.hash args[:card]
-
36
opts[:type] ||= args[:type] if args[:type]
-
# for /new/:type shortcut. we should handle in routing and deprecate this
-
36
opts[:name] ||= Card::Name.url_key_to_standard args[:mark]
-
36
opts
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/fetch_helper.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Haml)
-
#
-
1
module Haml;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/haml.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
include Card::Set::Format::HamlPaths
-
-
1
define_method :the_scope do
-
set_scope
-
end
-
-
1
define_method :haml_scope do
-
set_scope
-
end
-
-
# Renders haml templates. The haml template can be passed as string or
-
# block or a symbol that refers to a view template.
-
# @param args [Hash, String, Symbol]
-
# If a symbol is given then a template is expected in the corresponding view
-
# directory.
-
# @return [String] rendered haml as HTML
-
# @example render a view template
-
# # view/type/basic/my_template.haml:
-
# %p
-
# Hi
-
# = name
-
#
-
# # set/type/basic.rb:
-
# view :my_view do
-
# haml :my_template, name: "Joe: # => "<p>Hi Joe<p/>"
-
# end
-
# @example use a block to pass haml
-
# haml name: "Joe" do
-
# <<-HAML.strip_heredoc
-
# %p
-
# Hi
-
# = name
-
# HAML
-
# # => <p>Hi Joe</p>
-
# @example create a slot in haml code
-
# - haml_wrap do
-
# %p
-
# some haml
-
-
1
def haml *args, &block
-
102
if args.first.is_a? Symbol
-
102
process_haml_template(*args)
-
else
-
process_haml(*args, &block)
-
end
-
end
-
-
1
def haml_partial partial, locals={}
-
locals[:template_path] ||= @template_path
-
process_haml_template "_#{partial}".to_sym, locals
-
end
-
-
1
private
-
-
1
def process_haml *args
-
args.unshift yield if block_given?
-
haml_to_html(*args)
-
end
-
-
1
def process_haml_template template_name, *args
-
102
locals = args.first || {}
-
102
path = identify_template_path template_name, locals
-
102
with_template_path path do
-
102
haml_to_html ::File.read(path), *args
-
end
-
# rescue => e
-
# raise Card::Error, "HAML error #{template_name}: #{e.message}\n#{e.backtrace}"
-
end
-
-
1
def identify_template_path view, locals={}
-
102
base_path = locals.delete(:template_path) || caller_locations[2].path
-
102
haml_template_path view, base_path
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/haml.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (I18n)
-
#
-
1
module I18n;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/i18n.rb"; end
-
-
1
def tr key, args={}
-
2
::I18n.t key, args.reverse_merge(scope: Card::Set.scope(caller))
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def tr key, args={}
-
46
::I18n.t key, args.reverse_merge(scope: Card::Set.scope(caller))
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/i18n.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Initialize)
-
#
-
1
module Initialize;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/initialize.rb"; end
-
1
JUNK_INIT_ARGS = %w[missing skip_virtual id].freeze
-
-
1
module ClassMethods
-
1
def new args={}, _options={}
-
2899
with_normalized_new_args args do |normalized_args|
-
2899
super normalized_args
-
end
-
end
-
-
1
def with_normalized_new_args args={}
-
2921
args = (args || {}).stringify_keys
-
2921
delete_junk_args args
-
2921
normalize_type_args args
-
2921
normalize_content_args args
-
2921
yield args
-
end
-
-
1
private
-
-
1
def delete_junk_args args
-
11684
JUNK_INIT_ARGS.each { |a| args.delete(a) }
-
end
-
-
1
def normalize_type_args args
-
8763
%w[type type_code].each { |k| args.delete(k) if args[k].blank? }
-
end
-
-
1
def normalize_content_args args
-
2921
args.delete("content") if args["attach"] # should not be handled here!
-
2921
args["db_content"] = args.delete "content" if args["content"]
-
end
-
end
-
-
1
def initialize args={}
-
2899
args["name"] = initial_name args["name"]
-
-
2899
handle_set_modules args do
-
2899
handle_type args do
-
2899
super args # ActiveRecord #initialize
-
end
-
end
-
2899
self
-
end
-
-
1
def handle_set_modules args
-
2899
skip_modules = args.delete "skip_modules"
-
2899
yield
-
2899
include_set_modules unless skip_modules
-
end
-
-
1
def handle_type args
-
2921
type_lookup = args["type_lookup"]
-
2921
@supercard = args.delete "supercard"
-
-
2921
yield
-
2921
type_id_from_template if type_lookup == :force || (!type_id && type_lookup != :skip)
-
end
-
-
1
def initial_name name
-
2899
name.is_a?(String) ? name : Card::Name[name].to_s
-
end
-
-
1
def include_set_modules
-
10409
return self if @set_mods_loaded
-
-
4197
set_modules.each do |m|
-
7228
singleton_class.send :include, m
-
end
-
4197
assign_set_specific_attributes
-
4197
@uncacheable = @set_mods_loaded = true
-
4197
self
-
end
-
-
1
def uncacheable?
-
6755
@uncacheable == true
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/initialize.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Item)
-
#
-
1
module Item;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/item.rb"; end
-
1
def item_names _args={}
-
format._render_raw.split(/[,\n]/)
-
end
-
-
1
def item_cards _args={} # FIXME: this is inconsistent with item_names
-
34
[self]
-
end
-
-
1
def item_type
-
nil
-
end
-
-
1
def item_keys args={}
-
item_names(args).map do |item|
-
item.to_name.key
-
end
-
end
-
-
1
def item_count args={}
-
item_names(args).size
-
end
-
-
1
def items_to_content array
-
199
items = array.map { |i| standardize_item i }.reject(&:blank?)
-
20
self.content = items.to_pointer_content
-
end
-
-
1
def standardize_item item
-
179
Card::Name[item]
-
end
-
-
1
def include_item? item
-
item_names.include? Card::Name[item]
-
end
-
-
1
def add_item item
-
return if include_item? item
-
items_to_content(items_strings << item)
-
end
-
-
1
def drop_item item
-
item = Card::Name[item]
-
return unless include_item? item
-
items_to_content(item_names.reject { |i| i == item })
-
end
-
-
1
def insert_item index, name
-
new_names = item_names
-
new_names.delete name
-
new_names.insert index, name
-
items_to_content new_names
-
end
-
-
1
def replace_item old, new
-
return unless include_item? old
-
drop_item old
-
add_item new
-
end
-
-
# I think the following should work as add_item...
-
#
-
1
def add_id id
-
add_item "~#{id}"
-
end
-
-
1
def drop_id id
-
drop_item "~#{id}"
-
end
-
-
1
def insert_id index, id
-
insert_item index, "~#{id}"
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def item_links _args={}
-
raw(render_core).split(/[,\n]/)
-
end
-
-
1
def nest_item cardish, options={}, &block
-
options = item_view_options options
-
options[:nest_name] = Card::Name[cardish].s
-
nest cardish, options, &block
-
end
-
-
1
def implicit_item_view
-
view = voo_items_view || default_item_view
-
Card::View.normalize view
-
end
-
-
1
def voo_items_view
-
return unless voo && (items = voo.items)
-
items[:view]
-
end
-
-
1
def default_item_view
-
:name
-
end
-
-
1
def item_view_options new_options={}
-
options = (voo.items || {}).clone
-
options = options.merge new_options
-
options[:view] ||= implicit_item_view
-
determine_item_view_options_type options
-
options
-
end
-
-
1
def determine_item_view_options_type options
-
return if options[:type]
-
type_from_rule = card.item_type
-
options[:type] = type_from_rule if type_from_rule
-
end
-
-
1
def listing listing_cards, item_args={}
-
listing_cards.map do |item_card|
-
nest_item item_card, item_args do |rendered, item_view|
-
wrap_item rendered, item_view
-
end
-
end
-
end
-
-
1
def wrap_item item, _args={}
-
item # no wrap in base
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def wrap_item rendered, item_view
-
%(<div class="item-#{item_view}">#{rendered}</div>)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/item.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Layouts)
-
#
-
1
module Layouts;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/layouts.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
attr_reader :interior
-
-
1
def layout_nest
-
wrap_main { interior }
-
end
-
-
1
layout :pre do # {{_main|raw}}
-
wrap_with :pre do
-
layout_nest
-
end
-
end
-
-
1
layout :simple do
-
layout_nest
-
end
-
-
1
layout :no_side do # {{_main|open}}
-
<<-HTML.strip_heredoc
-
<header>#{nest :header, view: :core}</header>
-
<article>#{layout_nest}</article>
-
<footer>{nest :footer, view: :core}</footer>
-
HTML
-
end
-
-
1
layout :default do
-
<<-HTML.strip_heredoc
-
<header>#{nest :header, view: :core}</header>
-
<article>#{layout_nest}</article>
-
<aside>#{nest :sidebar, view: :core}</aside>
-
<footer>{nest :footer, view: :core}</footer>
-
HTML
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/layouts.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (LocationHistory)
-
#
-
1
module LocationHistory;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/location_history.rb"; end
-
1
event :discard_deleted_locations, :finalize, on: :delete do
-
76
Env.discard_locations_for self
-
76
configure_successful_deletion if success.target == self
-
end
-
-
1
event :save_current_location, before: :show_page, on: :read do
-
31
Env.save_location self
-
end
-
-
# TO DISCUSS: should this default behavior be directly in the controller?
-
# Or at least in decko?
-
1
def configure_successful_deletion
-
22
if Env.ajax?
-
1
success.card = self
-
1
success.view = :unknown unless success.view
-
else
-
21
success.target = :previous
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/location_history.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Name)
-
#
-
1
module Name;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/name.rb"; end
-
1
require "uuid"
-
-
1
module ClassMethods
-
1
def uniquify_name name, rename=:new
-
return name unless Card.exists? name
-
uniq_name = generate_alternative_name name
-
return uniq_name unless rename == :old
-
rename!(name, uniq_name)
-
name
-
end
-
-
1
def generate_alternative_name name
-
uniq_name = "#{name} 1"
-
uniq_name.next! while Card.exists?(uniq_name)
-
uniq_name
-
end
-
-
1
def rename! oldname, newname
-
Card[oldname].update! name: newname, update_referers: true
-
end
-
end
-
-
1
def name
-
96763
@name ||= left_id ? Card::Lexicon.lex_to_name([left_id, right_id]) : super.to_name
-
end
-
-
1
def key
-
15008
@key ||= left_id ? name.key : super
-
end
-
-
1
def name= newname
-
2979
@name = superize_name newname.to_name
-
2979
self.key = @name.key
-
2979
update_subcard_names @name
-
2979
write_attribute :name, (@name.simple? ? @name.s : nil)
-
2979
assign_side_ids
-
2979
@name
-
end
-
-
1
def assign_side_ids
-
2979
if name.simple?
-
1558
self.left_id = self.right_id = nil
-
else
-
1421
assign_side_id :left_id=, :left_name
-
1421
assign_side_id :right_id=, :right_name
-
end
-
end
-
-
# assigns left_id and right_id based on names.
-
# if side card is new, id is temporarily stored as -1
-
1
def assign_side_id side_id_equals, side_name
-
2842
side_id = Card::Lexicon.id(name.send(side_name)) || -1
-
2842
send side_id_equals, side_id
-
end
-
-
1
def superize_name cardname
-
2979
return cardname unless @supercard
-
8
@raw_name = cardname.s
-
8
@supercard.subcards.rename key, cardname.key
-
8
update_superleft cardname
-
8
cardname.absolute_name @supercard.name
-
end
-
-
1
def update_superleft cardname
-
100
@superleft = @supercard if cardname.field_of? @supercard.name
-
end
-
-
1
def key= newkey
-
2979
return if newkey == key
-
2940
update_cache_key key do
-
2940
write_attribute :key, (name.simple? ? newkey : nil)
-
2940
@key = newkey
-
end
-
2940
clean_patterns
-
2940
@key
-
end
-
-
1
def clean_patterns
-
2940
return unless patterns?
-
15
reset_patterns
-
15
patterns
-
end
-
-
1
def update_cache_key oldkey
-
2940
yield
-
2940
was_in_cache = Card.cache.soft.delete oldkey
-
2940
Card.write_to_soft_cache self if was_in_cache
-
end
-
-
1
def update_subcard_names new_name, name_to_replace=nil
-
2981
return unless @subcards
-
15
subcards.each do |subcard|
-
2
update_subcard_name subcard, new_name, name_to_replace if subcard.new?
-
end
-
end
-
-
1
def update_subcard_name subcard, new_name, name_to_replace
-
2
name_to_replace ||= name_to_replace_for_subcard subcard, new_name
-
2
subcard.name = subcard.name.swap name_to_replace, new_name.s
-
2
subcard.update_subcard_names new_name, name # needed? shouldn't #name= trigger this?
-
end
-
-
1
def name_to_replace_for_subcard subcard, new_name
-
# if subcard has a relative name like +C
-
# and self is a subcard as well that changed from +B to A+B then
-
# +C should change to A+B+C. #replace doesn't work in this case
-
# because the old name +B is not a part of +C
-
2
if subcard.name.starts_with_joint? && new_name.parts.first.present?
-
2
"".to_name
-
else
-
name
-
end
-
end
-
-
1
def autoname name
-
3
if Card.exists?(name) || Director.include?(name)
-
1
autoname name.next
-
else
-
2
name
-
end
-
end
-
-
# FIXME: use delegations and include all name functions
-
1
def simple?
-
8888
name.simple?
-
end
-
-
1
def junction?
-
1952
name.junction?
-
end
-
-
1
def raw_name
-
@raw_name || name
-
end
-
-
1
def left *args
-
case
-
1262
when simple? then nil
-
166
when superleft then superleft
-
when name_is_changing? && name.to_name.trunk_name == name_before_act.to_name
-
nil # prevent recursion when, eg, renaming A+B to A+B+C
-
else
-
970
Card.fetch name.left, *args
-
end
-
end
-
-
1
def right *args
-
5807
Card.fetch(name.right, *args) unless simple?
-
end
-
-
1
def [] *args
-
641
case args[0]
-
when Integer, Range
-
5
fetch_name = Array.wrap(name.parts[args[0]]).compact.join Card::Name.joint
-
5
Card.fetch(fetch_name, args[1] || {}) unless simple?
-
else
-
636
super
-
end
-
end
-
-
1
def trunk *args
-
238
simple? ? self : left(*args)
-
end
-
-
1
def tag *args
-
6
simple? ? self : Card.fetch(name.right, *args)
-
end
-
-
1
def left_or_new args={}
-
185
left(args) || Card.new(args.merge(name: name.left))
-
end
-
-
# NOTE: for all these helpers, method returns *all* fields/children/descendants.
-
# (Not just those current user has permission to read.)
-
-
1
def fields
-
26
field_ids.map { |id| Card[id] }
-
end
-
-
1
def field_names
-
field_ids.map { |id| Card::Name[id] }
-
end
-
-
1
def field_ids
-
17
child_ids :left
-
end
-
-
1
def each_child
-
106
child_ids.each do |id|
-
63
(child = Card[id]) && yield(child)
-
# check should not be needed (remove after fixing data problems)
-
end
-
end
-
-
# eg, A+B is a child of A and B
-
1
def child_ids side=nil
-
123
return [] unless id
-
123
side ||= name.simple? ? :part : :left_id
-
123
Auth.as_bot do
-
123
Card.search({ side => id, return: :id, limit: 0 }, "children of #{name}")
-
end
-
end
-
-
1
def each_descendant &block
-
29
each_child do |child|
-
11
yield child
-
11
child.each_descendant(&block)
-
end
-
end
-
-
1
def right_id= cardish
-
3011
write_card_or_id :right_id, cardish
-
end
-
-
1
def left_id= cardish
-
3030
write_card_or_id :left_id, cardish
-
end
-
-
1
def write_card_or_id attribute, cardish
-
17688
when_id_exists(cardish) { |id| write_attribute attribute, id }
-
end
-
-
1
def when_id_exists cardish, &block
-
8844
if (card_id = Card.id cardish)
-
5675
yield card_id
-
3169
elsif cardish.is_a? Card
-
53
with_id_after_store cardish, &block
-
else
-
3116
yield cardish # eg nil
-
end
-
end
-
-
# subcards are usually saved after super cards;
-
# after_store forces it to save the subcard first
-
# and callback afterwards
-
1
def with_id_after_store subcard
-
53
add_subcard subcard
-
106
subcard.director.after_store { |card| yield card.id }
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/name.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (NameEvents)
-
#
-
# STAGE: prepare to validate
-
1
module NameEvents;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/name_events.rb"; end
-
-
1
event :set_autoname, :prepare_to_validate, on: :create do
-
196
if name.blank? && (autoname_card = rule_card(:autoname))
-
2
self.name = autoname autoname_card.db_content
-
# FIXME: should give placeholder in approve phase
-
# and finalize/commit change in store phase
-
2
autoname_card.refresh.update_column :db_content, name
-
end
-
end
-
-
# STAGE: validate
-
-
1
event :validate_name, :validate, on: :save, changed: :name do
-
217
validate_legality_of_name
-
217
return if errors.any?
-
216
Card.write_to_soft_cache self
-
216
validate_uniqueness_of_name
-
end
-
-
1
event :validate_uniqueness_of_name, skip: :allowed do
-
# validate uniqueness of name
-
-
216
return unless (existing_id = Card::Lexicon.id key) && existing_id != id
-
# The above is a fast check but cannot detect if card is in trash
-
-
# TODO: perform the following as a remote-only fetch (not yet supported)
-
17
return unless (existing_card = Card.where(id: existing_id, trash: false).take)
-
-
1
errors.add :name, tr(:error_name_exists, name: existing_card.name)
-
end
-
-
1
event :validate_legality_of_name do
-
217
if name.length > 255
-
errors.add :name, tr(:error_too_long, length: name.length)
-
217
elsif name.blank?
-
1
errors.add :name, tr(:error_blank_name)
-
216
elsif name.parts.include? ""
-
errors.add :name, tr(:is_incomplete)
-
216
elsif !name.valid?
-
errors.add :name, tr(:error_banned_characters, banned: Card::Name.banned_array * " ")
-
216
elsif changing_existing_tag_to_junction?
-
errors.add :name, tr(:error_name_tag, name: name)
-
end
-
end
-
-
1
event :validate_key, after: :validate_name, on: :save do
-
217
if key.empty?
-
1
errors.add :key, tr(:error_blank_key) if errors.empty?
-
216
elsif key != name.key
-
errors.add :key, tr(:error_wrong_key, key: key, name: name)
-
end
-
end
-
-
# STAGE: store
-
-
1
event :expire_old_name, :store, changed: :name, on: :update do
-
18
Director.expirees << name_before_act
-
end
-
-
1
event :update_lexicon_on_create, :finalize, changed: :name, on: :create do
-
189
Card::Lexicon.add self
-
end
-
-
1
event :update_lexicon_on_rename, :finalize, changed: :name, on: :update do
-
18
Card::Lexicon.update self
-
end
-
-
1
def lex
-
207
simple? ? name : [left_id, right_id]
-
end
-
-
1
def old_lex
-
18
if (old_left_id = left_id_before_act)
-
[old_left_id, right_id_before_act]
-
else
-
18
name_before_act
-
end
-
end
-
-
1
event :prepare_left_and_right, :store, changed: :name, on: :save do
-
207
return if name.simple?
-
75
prepare_side :left
-
75
prepare_side :right
-
end
-
-
1
def prepare_side side
-
150
side_id = send "#{side}_id"
-
150
sidename = name.send "#{side}_name"
-
150
prepare_obstructed_side(side, side_id, sidename) ||
-
prepare_new_side(side, side_id, sidename)
-
end
-
-
1
def prepare_new_side side, side_id, sidename
-
150
return unless side_id == -1 || !Card[side_id]&.real?
-
-
83
sidecard = Director.card(sidename) || add_subcard(sidename)
-
83
send "#{side}_id=", sidecard
-
end
-
-
1
def prepare_obstructed_side side, side_id, sidename
-
150
return unless side_id && side_id == id
-
clear_name sidename
-
send "#{side}_id=", add_subcard(sidename)
-
true
-
end
-
-
1
private
-
-
1
def changing_existing_tag_to_junction?
-
216
return false unless changing_name_to_junction?
-
name_in_use_as_tag?
-
end
-
-
1
def name_in_use_as_tag?
-
!Card.where(right_id: id, trash: false).take.nil?
-
end
-
-
1
def changing_name_to_junction?
-
216
name.junction? && simple?
-
end
-
-
1
def old_name_in_way? sidecard
-
real? && sidecard&.simple? && id == sidecard&.id
-
end
-
-
1
def clear_name name
-
# move the current card out of the way, in case the new name will require
-
# re-creating a card with the current name, ie. A -> A+B
-
Card.where(id: id).update_all(name: nil, key: nil, left_id: nil, right_id: nil)
-
Card.expire name
-
Card::Lexicon.cache.reset # probably overkill, but this for an edge case...
-
# Card::Lexicon.delete id, key
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/name_events.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Observer)
-
#
-
1
module Observer;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/observer.rb"; end
-
1
%i[create update delete].each do |action|
-
3
event "observer_#{action}".to_sym, :integrate, on: action do
-
314
execute_card_events on: action
-
end
-
end
-
-
1
event :cache_delete_card_events, :store, on: :delete do
-
76
@card_event_cache = event_cards :on_delete
-
end
-
-
1
def execute_card_events args
-
314
setting = "on_#{args[:on]}".to_sym
-
314
event_cards(setting).each do |event_card|
-
event_card.deliver self
-
end
-
end
-
-
1
def event_cards setting
-
390
@card_event_cache ||
-
314
((event_rule = rule_card(setting)) && event_rule.extended_item_cards) ||
-
[]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/observer.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Pattern)
-
#
-
1
module Pattern;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/pattern.rb"; end
-
1
def patterns?
-
9676
defined? @patterns
-
end
-
-
1
def all_patterns
-
55154
@all_patterns ||= set_patterns.map { |sub| sub.new self }.compact
-
end
-
-
# new cards do not
-
1
def patterns
-
5752
@patterns ||= (new_card? ? all_patterns[1..-1] : all_patterns)
-
end
-
-
1
def reset_patterns
-
# Rails.logger.info "resetting patterns: #{name}"
-
4158
@patterns = @all_patterns = nil
-
4158
@template = @virtual = nil
-
4158
@set_mods_loaded = @set_modules = @set_names = @rule_set_keys = nil
-
4158
@junction_only = nil # only applies to set cards
-
4158
true
-
end
-
-
1
def safe_set_keys
-
130
patterns.map(&:safe_key).reverse * " "
-
end
-
-
1
def set_modules
-
4198
@set_modules ||= all_patterns[0..-2].reverse.map(&:module_list).flatten.compact
-
end
-
-
1
def set_format_modules klass
-
1849
@set_format_modules ||= {}
-
1849
@set_format_modules[klass] =
-
all_patterns[0..-2].reverse.map do |pattern|
-
6002
pattern.format_module_list klass
-
end.flatten.compact
-
end
-
-
1
def set_names
-
31
@set_names = patterns.map(&:to_s) if @set_names.nil?
-
31
@set_names
-
end
-
-
1
def in_set? set_module
-
patterns.map(&:module_key).include? set_module.shortname
-
end
-
-
1
def rule_set_keys
-
7009
@rule_set_keys ||= patterns.map(&:rule_set_key).compact
-
end
-
-
1
def include_module? set
-
singleton_class&.include? set
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/pattern.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Permissions)
-
#
-
1
module Permissions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/permissions.rb"; end
-
1
module ClassMethods
-
1
def repair_all_permissions
-
Card.where("(read_rule_class is null or read_rule_id is null) and trash is false")
-
.each do |broken_card|
-
broken_card.include_set_modules
-
broken_card.repair_permissions!
-
end
-
end
-
end
-
-
1
def repair_permissions!
-
rule_id, rule_class = permission_rule_id_and_class :read
-
update_columns read_rule_id: rule_id, read_rule_class: rule_class
-
end
-
-
# ok? and ok! are public facing methods to approve one action at a time
-
#
-
# fetching: if the optional :trait parameter is supplied, it is passed
-
# to fetch and the test is perfomed on the fetched card, therefore:
-
#
-
# trait: :account would fetch this card plus a tag codenamed :account
-
# trait: :roles, new: {} would initialize a new card with default ({})
-
# options.
-
-
1
def ok? action
-
2267
@ok ||= {}
-
2267
aok = @ok[Auth.as_id] ||= {}
-
2267
if (cached = aok[action])
-
310
cached
-
else
-
1957
aok[action] = send "ok_to_#{action}"
-
end
-
end
-
-
1
def ok! action
-
1
raise Card::Error::PermissionDenied, self unless ok? action
-
end
-
-
1
def who_can action
-
1301
permission_rule_card(action).item_cards.map(&:id)
-
end
-
-
1
def anyone_can? action
-
who_can(action).include? AnyoneID
-
end
-
-
1
def direct_rule_card action
-
234
direct_rule_id = rule_card_id action
-
234
require_permission_rule! direct_rule_id, action
-
234
Card.quick_fetch direct_rule_id
-
end
-
-
1
def permission_rule_id action
-
1721
if junction? && rule(action).match?(/^\[?\[?_left\]?\]?$/)
-
185
left_permission_rule_id action
-
else
-
1536
rule_card_id(action)
-
end
-
end
-
-
1
def permission_rule_id_and_class action
-
234
[permission_rule_id(action), direct_rule_card(action).rule_class_name]
-
end
-
-
1
def left_permission_rule_id action
-
185
lcard = left_or_new(skip_virtual: true, skip_modules: true)
-
185
if action == :create && lcard.real? && lcard.action != :create
-
6
action = :update
-
end
-
185
lcard.permission_rule_id action
-
end
-
-
1
def permission_rule_card action
-
1301
Card.fetch permission_rule_id(action)
-
end
-
-
1
def require_permission_rule! rule_id, action
-
234
return if rule_id
-
# RULE missing. should not be possible.
-
# generalize this to handling of all required rules
-
errors.add :permission_denied, tr(:error_no_action_rule, action: action, name: name)
-
raise Card::Error::PermissionDenied, self
-
end
-
-
1
def rule_class_name
-
234
trunk.type_id == SetID ? name.trunk_name.tag : nil
-
end
-
-
1
def you_cant what
-
52
"You don't have permission to #{what}"
-
end
-
-
1
def deny_because why
-
52
@permission_errors << why if @permission_errors
-
52
false
-
end
-
-
1
def permitted? action
-
1519
return false if Card.config.read_only # :read does not call #permit
-
1519
return true if Auth.always_ok?
-
-
1296
Auth.as_card.among? who_can(action)
-
end
-
-
1
def permit action, verb=nil
-
# not called by ok_to_read
-
1517
if Card.config.read_only
-
deny_because "Currently in read-only mode"
-
return false
-
end
-
-
1517
return true if permitted? action
-
47
verb ||= action.to_s
-
47
deny_because you_cant("#{verb} #{name.present? ? name : 'this'}")
-
end
-
-
1
def ok_to_create
-
1378
return false unless permit :create
-
1340
return true if simple?
-
-
80
%i[left right].each do |side|
-
# left is supercard; create permissions will get checked there.
-
160
next if side == :left && superleft
-
126
part_card = send side, new: {}
-
# if no card, there must be other errors
-
126
next unless part_card && part_card.new_card?
-
59
unless part_card.ok? :create
-
deny_because you_cant("create #{part_card.name}")
-
return false
-
end
-
end
-
80
true
-
end
-
-
1
def ok_to_read
-
368
return true if Auth.always_ok?
-
-
338
self.read_rule_id ||= permission_rule_id :read
-
338
return true if Auth.as_card.read_rules_hash[read_rule_id]
-
-
5
deny_because you_cant "read this"
-
end
-
-
1
def ok_to_update
-
60
return false unless permit(:update)
-
53
return true unless type_id_changed? && !permitted?(:create)
-
deny_because you_cant("change to this type (need create permission)")
-
end
-
-
1
def ok_to_delete
-
79
permit :delete
-
end
-
-
# don't know why we introduced this
-
# but we have to preserve read rules to make
-
# delete acts visible in recent changes -pk
-
# event :clear_read_rule, :store, on: :delete do
-
# self.read_rule_id = self.read_rule_class = nil
-
# end
-
-
1
event :set_read_rule, :store,
-
on: :save, changed: %i[type_id name] do
-
208
read_rule_id, read_rule_class = permission_rule_id_and_class(:read)
-
208
self.read_rule_id = read_rule_id
-
208
self.read_rule_class = read_rule_class
-
end
-
-
1
event :set_field_read_rules,
-
after: :set_read_rule, on: :update, changed: :type_id do
-
# find all cards with me as trunk and update their read_rule
-
# (because of *type plus right)
-
# skip if name is updated because will already be resaved
-
-
1
each_field_as_bot do |field|
-
1
field.refresh.update_read_rule
-
end
-
end
-
-
1
def update_field_read_rules
-
26
return unless type_id_changed? || read_rule_id_changed?
-
16
each_field_as_bot do |field|
-
8
field.update_read_rule if field.rule(:read) == "_left"
-
end
-
end
-
-
1
def each_field_as_bot
-
17
Auth.as_bot do
-
26
fields.each { |field| yield field }
-
end
-
end
-
-
1
def without_timestamps
-
26
Card.record_timestamps = false
-
26
yield
-
ensure
-
26
Card.record_timestamps = true
-
end
-
-
1
event :update_read_rule do
-
26
without_timestamps do
-
26
reset_patterns # why is this needed?
-
26
rcard_id, rclass = permission_rule_id_and_class :read
-
# these two are just to make sure vals are correct on current object
-
26
self.read_rule_id = rcard_id
-
26
self.read_rule_class = rclass
-
26
Card.where(id: id).update_all read_rule_id: rcard_id,
-
read_rule_class: rclass
-
26
expire :hard
-
26
update_field_read_rules
-
end
-
end
-
-
1
def add_to_read_rule_update_queue updates
-
@read_rule_update_queue = Array.wrap(@read_rule_update_queue).concat updates
-
end
-
-
1
event :check_permissions, :validate do
-
323
track_permission_errors do
-
323
ok? action_for_permission_check
-
end
-
end
-
-
1
def action_for_permission_check
-
323
commenting? ? :update : action
-
end
-
-
1
def track_permission_errors
-
323
@permission_errors = []
-
323
result = yield
-
329
@permission_errors.each { |msg| errors.add :permission_denied, msg }
-
323
@permission_errors = nil
-
323
result
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/permissions.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (References)
-
#
-
# frozen_string_literal: true
-
-
# Cards can refer to other cards in their content, eg via links and nests.
-
1
module References;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/references.rb"; end
-
# The card that refers is the "referer", the card that is referred to is
-
# the "referee". The reference itself has its own class (Card::Reference),
-
# which handles id-based reference tracking.
-
-
1
PARTIAL_REF_CODE = "P".freeze
-
-
# cards that refer to self
-
1
def referers
-
53
referer_cards_from_references references_in
-
end
-
-
# cards that include self
-
1
def nesters
-
referer_cards_from_references references_in.where(ref_type: "I")
-
end
-
-
1
def referer_cards_from_references references
-
53
references.map(&:referer_id).uniq.map(&Card.method(:fetch)).compact
-
end
-
-
# cards that self refers to
-
1
def referees
-
referees_from_references references_out
-
end
-
-
# cards that self includes
-
1
def nestees
-
referees_from_references references_out.where(ref_type: "I")
-
end
-
-
1
def referees_from_references references
-
references.map(&:referee_key).uniq.map { |key| Card.fetch key, new: {} }
-
end
-
-
# cards that refer to self by name
-
# (finds cards not yet linked by id)
-
1
def name_referers
-
Card.joins(:references_out).where card_references: { referee_key: key }
-
end
-
-
# replace references in card content
-
1
def replace_reference_syntax old_name, new_name
-
11
obj_content = Card::Content.new content, self
-
11
obj_content.find_chunks(Card::Content::Chunk::Reference).select do |chunk|
-
36
next unless (old_ref_name = chunk.referee_name)
-
36
next unless (new_ref_name = old_ref_name.swap old_name, new_name)
-
36
chunk.referee_name = chunk.replace_reference old_name, new_name
-
36
refs = Card::Reference.where referee_key: old_ref_name.key
-
36
refs.update_all referee_key: new_ref_name.key
-
end
-
-
11
obj_content.to_s
-
end
-
-
# delete old references from this card's content, create new ones
-
1
def update_references_out
-
237
delete_references_out
-
237
create_references_out
-
end
-
-
# interpret references from this card's content and
-
# insert entries in reference table
-
1
def create_references_out
-
237
ref_hash = {}
-
237
each_reference_out do |referee_name, ref_type|
-
241
interpret_reference ref_hash, referee_name, ref_type
-
end
-
237
return if ref_hash.empty?
-
66
Card::Reference.mass_insert reference_values_array(ref_hash)
-
end
-
-
# delete references from this card
-
1
def delete_references_out
-
313
raise "id required to delete references" if id.nil?
-
313
Card::Reference.where(referer_id: id).delete_all
-
end
-
-
# interpretation phase helps to prevent duplicate references
-
# results in hash like:
-
# { referee1_key: [referee1_id, referee1_type2],
-
# referee2_key...
-
# }
-
1
def interpret_reference ref_hash, raw_referee_name, ref_type
-
275
with_normalized_referee raw_referee_name do |referee_name, referee_key, referee_id|
-
258
ref_hash[referee_key] ||= [referee_id]
-
258
ref_hash[referee_key] << ref_type
-
258
interpret_partial_references ref_hash, referee_name unless referee_id
-
end
-
end
-
-
# Partial references are needed to track references to virtual cards.
-
# For example a link to virual card [[A+*self]] won't have a referee_id,
-
# but when A's name is changed we have to find and update that link.
-
1
def interpret_partial_references ref_hash, referee_name
-
28
return if referee_name.simple?
-
17
[referee_name.left, referee_name.right].each do |sidename|
-
34
interpret_reference ref_hash, sidename, PARTIAL_REF_CODE
-
end
-
end
-
-
# translate interpreted reference hash into values array,
-
# removing duplicate and unnecessary ref_types
-
1
def reference_values_array ref_hash
-
66
values = []
-
66
ref_hash.each do |referee_key, hash_val|
-
248
referee_id = hash_val.shift || "null"
-
248
ref_types = hash_val.uniq
-
248
ref_types.delete PARTIAL_REF_CODE if ref_types.size > 1
-
# partial references are not necessary if there are explicit references
-
248
ref_types.each do |ref_type|
-
248
values << [id, referee_id, "'#{referee_key}'", "'#{ref_type}'"]
-
end
-
end
-
66
values
-
end
-
-
# invokes the given block for each reference in content with
-
# the reference name and reference type
-
1
def each_reference_out
-
219
content_object.find_chunks(Card::Content::Chunk::Reference).each do |chunk|
-
94
yield chunk.referee_name, chunk.reference_code
-
end
-
end
-
-
1
def has_nests?
-
content_object.has_chunk? Card::Content::Chunk::Nest
-
end
-
-
1
def content_object
-
219
Card::Content.new content, self
-
end
-
-
1
protected
-
-
# test for updating referer content
-
1
event :prepare_referer_update, :validate, on: :update, changed: :name do
-
21
self.update_referers = ![nil, false, "false"].member?(update_referers)
-
end
-
-
# on rename, update names in cards that refer to self by name (as directed)
-
1
event :update_referer_content, :finalize, on: :update, when: :update_referers do
-
5
referers.each do |card|
-
11
next if card.structure
-
11
card.skip_event! :validate_renaming, :check_permissions
-
11
card.content = card.replace_reference_syntax name_before_act, name
-
11
attach_subcard card
-
end
-
end
-
-
# on rename, when NOT updating referer content, update references to ensure
-
# that partial references are correctly tracked
-
# eg. A links to X+Y. if X+Y is renamed and we're not updating the link in A,
-
# then we need to be sure that A has a partial reference
-
1
event :update_referer_references_out, :finalize,
-
on: :update, when: :not_update_referers do
-
48
referers.map(&:update_references_out)
-
end
-
-
# when name changes, update references to card
-
1
event :refresh_references_in, :finalize, on: :save do
-
253
Card::Reference.unmap_referees id if action == :update && !update_referers
-
253
Card::Reference.map_referees key, id
-
end
-
-
# when content changes, update references to other cards
-
1
event :refresh_references_out, :finalize, on: :save, changed: :content do
-
221
update_references_out
-
end
-
-
# clean up reference table when card is deleted
-
1
event :clear_references, :finalize, on: :delete do
-
76
delete_references_out
-
76
Card::Reference.unmap_referees id
-
end
-
-
1
def not_update_referers
-
53
!update_referers
-
end
-
-
1
private
-
-
1
def with_normalized_referee referee_name
-
275
return unless referee_name # eg commented nest has no referee_name
-
275
referee_name = referee_name.to_name
-
275
referee_key = referee_name.key
-
275
return if referee_key == key # don't create self reference
-
258
yield referee_name, referee_key, Card::Lexicon.id(referee_name)
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/references.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Rename)
-
#
-
1
module Rename;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/rename.rb"; end
-
1
event :rename_in_trash, after: :expire_old_name, on: :update do
-
26
existing_card = Card.find_by_key_and_trash name.key, true
-
26
return if !existing_card || existing_card == self
-
8
existing_card.name = existing_card.name + "*trash"
-
8
existing_card.rename_in_trash_without_callbacks
-
8
existing_card.save!
-
end
-
-
1
event :validate_renaming, :validate, on: :update, changed: :name, skip: :allowed do
-
21
return if name_before_act&.to_name == name # just changing to new variant
-
20
errors.add :content, tr(:cannot_change_content) if content_is_changing?
-
20
errors.add :type, tr(:cannot_change_type) if type_is_changing?
-
20
detect_illegal_compound_names
-
end
-
-
1
event :cascade_name_changes, :finalize, on: :update, changed: :name do
-
18
each_descendant do |d|
-
11
d.action = :update
-
11
update_referers ? d.update_referers : d.update_referer_references_out
-
11
d.refresh_references_in
-
11
d.refresh_references_out
-
11
d.expire
-
end
-
end
-
-
1
def changed_from_simple_to_compound?
-
20
name.compound? && name_before_act.to_name.simple?
-
end
-
-
1
def detect_illegal_compound_names
-
20
return unless changed_from_simple_to_compound? && child_ids(:right).present?
-
errors.add :name, "illegal name change; existing names end in +#{name_before_act}"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/rename.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Rules)
-
#
-
1
module Rules;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/rules.rb"; end
-
1
def rule setting_code
-
220
rule_card(setting_code, skip_modules: true)&.db_content
-
end
-
-
1
def rule_card setting_code, options={}
-
5177
Card.fetch rule_card_id(setting_code), options
-
end
-
-
1
def rule_card_id setting_code
-
6947
rule_id_lookup Card::Rule.rule_cache, setting_code
-
end
-
-
1
def preference setting_code, user=nil
-
62
preference_card(setting_code, user, skip_modules: true)&.db_content
-
end
-
-
1
def preference_card setting_code, user=nil, options={}
-
62
Card.fetch preference_card_id(setting_code, user), options
-
end
-
-
1
def preference_card_id setting_code, user=nil
-
62
return unless (user_id = preference_user_id user)
-
62
rule_id_lookup Card::Rule.preference_cache,
-
"#{setting_code}+#{user_id}",
-
"#{setting_code}+#{AllID}"
-
end
-
-
1
def is_rule?
-
5260
is_standard_rule? || is_preference?
-
end
-
-
1
def is_standard_rule?
-
5260
(r = right(skip_modules: true)) &&
-
r.type_id == SettingID &&
-
468
(l = left(skip_modules: true)) &&
-
l.type_id == SetID
-
end
-
-
1
def is_preference?
-
4866
name.parts.length > 2 &&
-
383
(r = right(skip_modules: true)) &&
-
r.type_id == SettingID &&
-
5
(set = self[0..-3, skip_modules: true]) &&
-
set.type_id == SetID &&
-
(user = self[-2, skip_modules: true]) &&
-
(user.type_id == UserID || user.codename == :all)
-
end
-
-
# FIXME: move to a better place (if still needed) and use codenames
-
1
def related_sets with_self=false
-
# refers to sets that users may configure from the current card -
-
# NOT to sets to which the current card belongs
-
-
sets = []
-
sets << ["#{name}+*self", Card::Set::Self.label(name)] if with_self
-
if known? && name.simple?
-
sets << ["#{name}+*right", Card::Set::Right.label(name)]
-
end
-
sets
-
end
-
-
1
private
-
-
1
def preference_user_id user
-
62
case user
-
62
when Integer then user;
-
when Card then user
-
when nil then Auth.current_id
-
else
-
raise Card::ServerError, "invalid preference user"
-
end
-
end
-
-
1
def rule_id_lookup lookup_hash, cache_suffix, fallback_suffix=nil
-
7009
rule_set_keys.each do |rule_set_key|
-
25234
rule_id = lookup_hash["#{rule_set_key}+#{cache_suffix}"]
-
25234
rule_id ||= fallback_suffix && lookup_hash["#{rule_set_key}+#{fallback_suffix}"]
-
25234
return rule_id if rule_id
-
end
-
nil
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/rules.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (States)
-
#
-
# All cards have one (and only one) of these three states: real, virtual, and unknown.
-
#
-
# - *real* cards are stored in the database (but not in the trash) and have a unique id.
-
# - *virtual* cards are not real, but they act real based on rules. For example,
-
# Home+*editors does a search for all the users who have edited the "Home" card.
-
# There are many other similar cards that search for things like references, children,
-
# etc. But we don't store all these cards in the database; we generate them dynamically
-
1
module States;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/states.rb"; end
-
# based on the names.
-
# - *unknown* cards are everything else.
-
#
-
# These states are frequently grouped as follows:
-
#
-
# - *known* cards are either _real_ or _virtual_
-
# - *new* (or *unreal*) cards are either _unknown_ or _virtual_
-
-
1
module ClassMethods
-
1
def real? mark
-
35
quick_fetch(mark).present?
-
end
-
1
alias exist? real?
-
1
alias exists? real?
-
-
1
def known? mark
-
160
fetch(mark).present?
-
end
-
end
-
-
# @return [Symbol] :real, :virtual, or :unknown
-
1
def state anti_fishing=true
-
case
-
when !known? then :unknown
-
when anti_fishing && !ok?(:read) then :unknown
-
when real? then :real
-
when virtual? then :virtual
-
else :wtf
-
end
-
end
-
-
# @return [True/False]
-
1
def real?
-
1820
!unreal?
-
end
-
-
# Virtual cards are structured, compound cards that are not stored in the database. You
-
# can create virtual cards with structure rules.
-
#
-
# Some cards with hard-coded content will also override the #virtual? method. This
-
# is established practice, but it is NOT advisable to override any of the other
-
# state methods.
-
#
-
# @return [True/False]
-
1
def virtual?
-
525
if @virtual.nil?
-
244
@virtual = real? || name.simple? ? false : structure.present?
-
end
-
525
@virtual
-
end
-
-
# @return [True/False]
-
1
def unknown?
-
63
!known?
-
end
-
-
# @return [True/False]
-
1
def known?
-
1395
real? || virtual?
-
end
-
-
# @return [True/False]
-
1
def new?
-
85638
new_record? || # not yet in db (from ActiveRecord)
-
!@from_trash.nil? # in process of restoration from trash
-
end
-
1
alias new_card? new?
-
1
alias unreal? new?
-
-
# has not been edited directly by human users. bleep blorp.
-
1
def pristine?
-
new_card? || !user_changes?
-
end
-
-
1
def user_changes?
-
actions.joins(:act).where("card_acts.actor_id != ?", WagnBotID).exists?
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/states.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Subcards)
-
#
-
1
module Subcards;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/subcards.rb"; end
-
1
def field tag, opts={}
-
2
Card.fetch name.field(tag), opts
-
end
-
-
1
def subcard card_name
-
subcards.card card_name
-
end
-
-
1
def subfield field_name
-
6
subcards.field field_name
-
end
-
-
1
def field? tag
-
2
field(tag) || subfield(tag)
-
end
-
-
1
def subcards
-
4540
@subcards ||= Card::Subcards.new self
-
end
-
-
1
def subcards?
-
2
subcards.present?
-
end
-
-
1
def expire_subcards
-
subcards.clear
-
end
-
-
# phase_method :attach_subcard, before: :store do |name_or_card, args=nil|
-
# TODO: handle differently in different stages
-
1
def add_subcard name_or_card, args={}
-
182
subcards.add name_or_card, args
-
end
-
1
alias_method :attach_subcard, :add_subcard
-
-
1
def add_subcard! name_or_card, args={}
-
subcard = subcards.add name_or_card, args
-
subcard.director.reset_stage
-
subcard
-
end
-
1
alias_method :attach_subcard!, :add_subcard!
-
-
# phase_method :attach_subfield, before: :approve do |name_or_card, args=nil|
-
1
def attach_subfield name_or_card, args={}
-
8
subcards.add_field name_or_card, args
-
end
-
1
alias_method :add_subfield, :attach_subfield
-
-
1
def attach_subfield! name_or_card, args={}
-
subcard = subcards.add_field name_or_card, args
-
subcard.director.reset_stage
-
subcard
-
end
-
-
1
def detach_subcard name_or_card
-
subcards.remove name_or_card
-
end
-
1
alias_method :remove_subcard, :detach_subcard
-
-
1
def detach_subfield name_or_card
-
subcards.remove_field name_or_card
-
end
-
1
alias_method :remove_subfield, :detach_subfield
-
-
1
def clear_subcards
-
subcards.clear
-
end
-
-
# ensures subfield is present
-
# does NOT override subfield content if already present
-
1
def ensure_subfield field_name, args={}
-
if subfield_present? field_name
-
subfield field_name
-
else
-
add_subfield field_name, args
-
end
-
end
-
-
1
def subfield_present? field_name
-
subfield(field_name)&.content&.present?
-
end
-
-
1
def deep_clear_subcards
-
subcards.deep_clear
-
end
-
-
1
def handle_subcard_errors
-
3528
subcards.each do |subcard|
-
1357
subcard.errors.each do |field, err|
-
4
subcard_error subcard, field, err
-
end
-
1357
subcard.errors.clear
-
end
-
end
-
-
1
def subcard_error subcard, field, err
-
4
err = "#{field} #{err}" unless %i[content abort].member? field
-
4
errors.add subcard.name.from(name), err
-
end
-
-
1
event :reject_empty_subcards, :prepare_to_validate do
-
332
subcards.each_with_key do |subcard, key|
-
42
next unless subcard.new? && subcard.unfilled?
-
remove_subcard(key)
-
director.subdirectors.delete(subcard)
-
end
-
end
-
-
# check when deleting field that left has not also been deleted
-
1
def trashed_left?
-
1
l = left
-
1
!l || l.trash
-
end
-
-
# check when renaming field that it is not actually the same field
-
# (eg on a renamed trunk)
-
1
def same_field?
-
3
(left_id == left_id_before_act) && (right_id == right_id_before_act)
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/subcards.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Tabs)
-
#
-
1
module Tabs;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/tabs.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :tabs do
-
construct_tabs "tabs"
-
end
-
-
1
def construct_tabs tab_type
-
tabs = { active: {}, paths: {} }
-
voo.items[:view] ||= :content
-
card.each_item_name_with_options(_render_raw) do |name, options|
-
construct_tab tabs, name, options
-
end
-
tabs tabs[:paths], tabs[:active][:name], tab_type: tab_type, load: :lazy do
-
tabs[:active][:content]
-
end
-
end
-
-
1
def construct_tab tabs, name, explicit_options
-
tab_options = item_view_options explicit_options
-
tabs[:paths][name] = {
-
title: nest(name, view: :title, title: tab_options[:title]),
-
path: nest_path(name, tab_options).html_safe
-
}
-
return unless tabs[:active].empty?
-
tabs[:active] = { name: name, content: nest(name, tab_options) }
-
end
-
-
# def tab_title title, name
-
# return name unless title
-
# name.to_name.title title, @context_names
-
# end
-
-
1
view :pills do
-
construct_tabs "pills"
-
end
-
-
1
view :tabs_static do
-
construct_static_tabs "tabs"
-
end
-
-
1
view :pills_static do
-
construct_static_tabs "pills"
-
end
-
-
1
def construct_static_tabs tab_type
-
tabs = {}
-
card.item_cards.each do |item|
-
tabs[item.name] = nest item, item_view_options(args)
-
end
-
tabs tabs, nil, tab_type: tab_type
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/tabs.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Templating)
-
#
-
1
module Templating;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/templating.rb"; end
-
-
1
def is_template?
-
return @is_template unless @is_template.nil?
-
-
@is_template = name.trait_name? :structure, :default
-
end
-
-
1
def is_structure?
-
1223
return @is_structure unless @is_structure.nil?
-
-
543
@is_structure = name.trait_name? :structure
-
end
-
-
1
def template
-
# currently applicable templating card.
-
# note that a *default template is never returned for an existing card.
-
5216
@template ||= begin
-
3312
@virtual = false
-
-
3312
if new_card?
-
926
new_card_template
-
else
-
2386
structure_rule_card
-
end
-
end
-
end
-
-
1
def default_type_id
-
Card.default_type_id
-
end
-
-
1
def new_card_template
-
926
default = rule_card :default, skip_modules: true
-
-
926
dup_card = dup
-
926
dup_card.type_id = default&.type_id || default_type_id
-
-
926
if (structure = dup_card.structure_rule_card)
-
142
@virtual = true if junction?
-
142
self.type_id = structure.type_id if assign_type_to?(structure)
-
142
structure
-
else
-
784
default
-
end
-
end
-
-
1
def assign_type_to? structure
-
142
return if type_id == structure.type_id
-
104
structure.assigns_type?
-
end
-
-
1
def assigns_type?
-
# needed because not all *structure templates govern the type of set members
-
# for example, X+*type+*structure governs all cards of type X,
-
# but the content rule does not (in fact cannot) have the type X.
-
119
pattern_code = Card.quick_fetch(name.trunk_name.tag_name)&.codename
-
119
return unless pattern_code && (set_class = Set::Pattern.find pattern_code)
-
-
119
set_class.assigns_type
-
end
-
-
1
def structure
-
3277
return unless template && template.is_structure?
-
109
template
-
end
-
-
1
def structure_rule_card
-
3312
return unless (card = rule_card :structure, skip_modules: true)
-
-
156
card.db_content&.strip == "_self" ? nil : card
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/templating.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Trash)
-
#
-
1
module Trash;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/trash.rb"; end
-
1
Self::Admin.add_to_basket(
-
:tasks,
-
name: :empty_trash,
-
irreversible: true,
-
execute_policy: -> { Card.empty_trash },
-
stats: {
-
title: "trashed cards",
-
count: -> { Card.where(trash: true) },
-
link_text: "empty trash",
-
task: "empty_trash"
-
}
-
)
-
-
1
module ClassMethods
-
1
def empty_trash
-
Card.delete_trashed_files
-
Card.where(trash: true).in_batches.update_all(left_id: nil, right_id: nil)
-
Card.where(trash: true).in_batches.delete_all
-
Card::Action.delete_cardless
-
Card::Change.delete_actionless
-
Card::Act.delete_actionless
-
Card::Reference.unmap_if_referee_missing
-
Card::Reference.delete_if_referer_missing
-
end
-
-
# deletes any file not associated with a real card.
-
1
def delete_trashed_files
-
dir = Cardio.paths["files"].existent.first
-
# TODO: handle cloud files
-
return unless dir
-
-
trashed_card_ids = all_trashed_card_ids
-
file_ids = all_file_ids
-
file_ids.each do |file_id|
-
next unless trashed_card_ids.member?(file_id)
-
raise Card::Error, tr(:exception_almost_deleted) if Card.exists?(file_id)
-
::FileUtils.rm_rf "#{dir}/#{file_id}", secure: true
-
end
-
end
-
-
1
def all_file_ids
-
dir = Card.paths["files"].existent.first
-
Dir.entries(dir)[2..-1].map(&:to_i)
-
end
-
-
1
def all_trashed_card_ids
-
trashed_card_sql = %( select id from cards where trash is true )
-
sql_results = Card.connection.select_all(trashed_card_sql)
-
sql_results.map(&:values).flatten.map(&:to_i)
-
end
-
end
-
-
1
def delete args={}
-
8
add_to_trash args do |delete_args|
-
8
update delete_args
-
end
-
end
-
-
1
def delete! args={}
-
19
add_to_trash args do |delete_args|
-
19
update! delete_args
-
end
-
end
-
-
1
def add_to_trash args
-
27
return if new_card?
-
27
yield args.merge trash: true
-
end
-
-
1
event :manage_trash, :prepare_to_store, on: :create do
-
190
pull_from_trash!
-
190
self.trash = false
-
190
true
-
end
-
-
1
def pull_from_trash!
-
190
return unless (id = Card::Lexicon.id key) # name is already known
-
11
return unless (trashed_card = Card.where(id: id).take)&.trash
-
# confirm name is actually in trash
-
-
11
db_attributes["id"] = trashed_card.db_attributes["id"]
-
# id_in_database returns existing card id
-
-
11
@from_trash = true
-
11
@new_record = false
-
end
-
-
1
def db_attributes
-
22
send(:mutations_from_database).send :attributes
-
end
-
-
1
event :validate_delete, :validate, on: :delete do
-
78
unless codename.blank?
-
errors.add :delete, tr(:error_system_card, name: name, codename: codename)
-
end
-
-
undeletable_all_rules_tags =
-
78
%w[default style layout create read update delete]
-
# FIXME: HACK! should be configured in the rule
-
-
78
if junction? && left&.codename == :all &&
-
undeletable_all_rules_tags.member?(right.codename.to_s)
-
errors.add :delete, tr(:error_indestructible, name: name)
-
end
-
-
78
errors.add :delete, tr(:error_user_edits, name: name) if account && has_edits?
-
end
-
-
1
event :validate_delete_children, after: :validate_delete, on: :delete do
-
78
return if errors.any?
-
77
each_child do |child|
-
52
next unless child
-
# prevents errors in cases where a child is deleted prior to this point
-
# and thus is not returned by the fetch in #children
-
-
52
delete_as_subcard child
-
# next if child.valid?
-
# child.errors.each do |field, message|
-
# errors.add field, "can't delete #{child.name}: #{message}"
-
# end
-
end
-
end
-
-
1
def delete_as_subcard subcard
-
52
subcard.trash = true
-
52
add_subcard subcard
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/trash.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Type)
-
#
-
1
module Type;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/type.rb"; end
-
-
1
module ClassMethods
-
1
def default_type_id
-
3
@@default_type_id ||= Card[:all].fetch(:default, skip_modules: true).type_id
-
end
-
end
-
-
1
def type_card
-
6270
return if type_id.nil?
-
6270
Card.quick_fetch type_id.to_i
-
end
-
-
1
def type_code
-
427
Card::Codename[type_id.to_i]
-
end
-
-
1
def type_name
-
6257
type_card.try :name
-
end
-
-
1
alias_method :type, :type_name
-
-
1
def type_name_or_default
-
7
type_card.try(:name) || Card.quick_fetch(Card.default_type_id).name
-
end
-
-
1
def type_cardname
-
type_card.try :name
-
end
-
-
1
def type= type_name
-
self.type_id = Card.fetch_id type_name
-
end
-
-
1
def type_id= card_or_id
-
2803
write_card_or_id :type_id, card_or_id
-
end
-
-
1
def type_id_from_template
-
524
return unless name && (t = template)
-
524
reset_patterns # still necessary even with new template handling?
-
524
self.type_id = t.type_id
-
end
-
-
1
event :validate_type_change, :validate, on: :update, changed: :type_id do
-
1
if (c = dup) && c.action == :create && !c.valid?
-
errors.add :type, tr(
-
:error_cant_change_errors,
-
name: name, type_id: type_id,
-
error_messages: c.errors.full_messages
-
)
-
end
-
end
-
-
1
event :validate_type, :validate, changed: :type_id, on: :save do
-
197
errors.add :type, tr(:error_no_such_type) unless type_name
-
-
197
if (rt = structure) && rt.assigns_type? && type_id != rt.type_id
-
errors.add :type, tr(:error_hard_templated, name: name, type_name: rt.type_name)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/type.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (UpdateReadRules)
-
#
-
1
module UpdateReadRules;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/update_read_rules.rb"; end
-
-
# FIXME: the following don't really belong here, but they have to come after
-
# the reference stuff. we need to organize a bit!
-
-
1
event :update_rule_cache, :finalize, when: :is_rule? do
-
10
Card::Rule.clear_rule_cache
-
end
-
-
1
event :expire_related, :finalize do
-
318
reset_patterns
-
318
structuree_names.each { |name| Director.expirees << name } if is_structure?
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/update_read_rules.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Utils)
-
#
-
1
module Utils;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/core/set/all/utils.rb"; end
-
1
module ClassMethods
-
1
def merge_list attribs, opts={}
-
unmerged = []
-
attribs.each do |row|
-
if merge row["name"], row, opts
-
Rails.logger.info "merged #{row['name']}"
-
else
-
unmerged.push row
-
end
-
end
-
-
if unmerged.empty?
-
Rails.logger.info "successfully merged all!"
-
else
-
unmerged_json = JSON.pretty_generate unmerged
-
report_unmerged_json unmerged_json, opts[:output_file]
-
end
-
unmerged
-
end
-
-
1
def report_unmerged_json unmerged_json, output_file
-
if output_file
-
::File.open output_file, "w" do |f|
-
f.write unmerged_json
-
end
-
else
-
Rails.logger.info "failed to merge:\n\n#{unmerged_json}"
-
end
-
end
-
-
1
def merge name, attribs={}, opts={}
-
# puts "merging #{name}"
-
card = fetch name, new: {}
-
return unless mergeable? card, opts[:pristine]
-
-
resolve_file_attributes! attribs
-
card.safe_update! attribs
-
end
-
-
1
private
-
-
1
def resolve_file_attributes! attribs
-
%i[image file].each do |attach|
-
next unless attribs[attach] && attribs[attach].is_a?(String)
-
-
attribs[attach] = ::File.open(attribs[attach])
-
end
-
end
-
-
1
def mergeable? card, pristine_only
-
return true unless pristine_only
-
-
!card.pristine?
-
end
-
end
-
-
# separate name and other attributes
-
1
def safe_update! attribs
-
separate_name_update! attribs.delete("name") unless new?
-
update! attribs if attribs.present?
-
end
-
-
1
def separate_name_update! new_name
-
return if new_name.to_s == name.to_s
-
-
update! name: new_name
-
end
-
-
# rubocop:disable Style/GlobalVars
-
1
def measure desc
-
$times ||= {}
-
res = nil
-
t = Benchmark.measure do
-
res = yield
-
end
-
$times[desc] = $times.key?(desc) ? t + $times[desc] : t
-
puts "#{desc}: #{t}".red
-
res
-
end
-
# rubocop:enable Style/GlobalVars
-
-
1
def mod_root modname
-
36
if (spec = Gem::Specification.find_by_name "card-mod-#{modname}")
-
36
spec.full_gem_path
-
else
-
"#{Cardio.gem_root}/mod/#{modname}"
-
end
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
delegate :measure, to: :card
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set/all/utils.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (AllCss)
-
#
-
1
module AllCss;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/all_css.rb"; end
-
-
2
module CssFormat; module_parent.send :register_set_format, Card::Format::CssFormat, self; extend Card::Set::AbstractFormat
-
1
def default_nest_view
-
:raw
-
end
-
-
1
def show view, args
-
view ||= :content
-
render! view, args
-
end
-
-
1
view :titled do
-
major_comment(%( Style Card: \\"#{card.name}\\" )) + _render_core
-
end
-
-
1
view :content do
-
_render_core
-
end
-
-
1
view :unknown do
-
major_comment "MISSING Style Card: #{card.name}"
-
end
-
-
1
view :import do
-
_render_core
-
end
-
-
1
view :url, perms: :none do
-
path mark: card.name, format: :css
-
end
-
-
1
def major_comment comment, char="-"
-
edge = %(/* #{char * (comment.length + 4)} */)
-
main = %(/* #{char} #{comment} #{char} */)
-
"#{edge}\n#{main}\n#{edge}\n\n"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/all_css.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (AllCsv)
-
#
-
1
module AllCsv;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/all_csv.rb"; end
-
1
require "csv"
-
-
2
module CsvFormat; module_parent.send :register_set_format, Card::Format::CsvFormat, self; extend Card::Set::AbstractFormat
-
1
def default_nest_view
-
:core
-
end
-
-
1
def default_item_view
-
depth.zero? ? :csv_row : :name
-
end
-
-
1
view :core do
-
if (item_view_options[:view] == :name_with_fields) && focal?
-
title_row("item name") + name_with_field_rows
-
else
-
super()
-
end
-
end
-
-
1
view :csv_row do
-
array = _render_raw.scan(/\{\{[^\}]*\}\}/).map do |inc|
-
process_content(inc).strip
-
end
-
-
CSV.generate_line(array).strip
-
# strip is because search already joins with newlines
-
end
-
-
1
view :unknown do
-
""
-
end
-
-
1
view :name_with_fields do
-
CSV.generate_line name_with_fields_row
-
end
-
-
1
def name_with_fields_row
-
nested_field_names.each_with_object([card.name]) do |field_name, row|
-
row << nest(field_name)
-
end
-
end
-
-
1
def name_with_field_rows
-
return [] unless row_card_names.present?
-
-
row_card_names.map do |item_name|
-
CSV.generate_line row_from_field_names(item_name, columns)
-
end.join
-
end
-
-
1
def row_card_names
-
@row_cards ||= card.item_names
-
end
-
-
1
def columns
-
csv_structure_card.format.nested_field_names.map(&:tag)
-
end
-
-
1
def csv_structure_card
-
card.rule_card(:csv_structure) || Card.fetch(row_card_names.first)
-
end
-
-
1
def row_from_field_names parent_name, field_names, view=:core
-
field_names.each_with_object([parent_name]) do |field, row|
-
row << nest([parent_name, field], view: view)
-
end
-
end
-
-
1
def title_row extra_titles=nil
-
titles = column_titles extra_titles
-
return "" unless titles.present?
-
CSV.generate_line titles.map(&:upcase)
-
end
-
-
1
def column_titles extra_titles=nil
-
res = Array extra_titles
-
card1 = Card.fetch card.item_names(limit: 1).first
-
card1.nest_chunks.each do |chunk|
-
res << column_title(chunk.options)
-
end
-
res.compact
-
end
-
-
1
def column_title opts
-
if opts[:title]
-
opts[:title]
-
elsif %w[name link].member? opts[:view]
-
opts[:view]
-
else
-
opts[:nest_name].to_name.tag
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/all_csv.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (AllJs)
-
#
-
1
module AllJs;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/all_js.rb"; end
-
-
2
module JsFormat; module_parent.send :register_set_format, Card::Format::JsFormat, self; extend Card::Set::AbstractFormat
-
1
def default_item_view
-
:core
-
end
-
-
1
view :source do
-
path format: :js
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/all_js.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Base)
-
#
-
1
module Base;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/base.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def show view, args
-
3
view ||= :core
-
3
render! view, args.merge(main_nest_options)
-
end
-
-
# NAME VIEWS
-
-
1
view :name, compact: true, perms: :none do
-
8
name_variant safe_name
-
end
-
-
1
def safe_name
-
31
card&.name
-
end
-
-
1
def name_variant name
-
163
voo.variant ? name.to_name.vary(voo.variant) : name
-
end
-
-
1
view(:key, compact: true, perms: :none) { card.key }
-
5
view(:linkname, compact: true, perms: :none) { card.name.url_key }
-
5
view(:url, compact: true, perms: :none) { card_url _render_linkname }
-
-
1
view :url_link, compact: true, perms: :none do
-
link_to_resource card_url(_render_linkname)
-
end
-
-
1
view :link, compact: true, perms: :none do
-
14
link_view
-
end
-
-
1
view :nav_link, compact: true, perms: :none do
-
link_view class: "nav-link"
-
end
-
-
1
def link_view opts={}
-
37
opts[:known] = card.known?
-
37
specify_type_in_link! opts
-
37
link_to_card card.name, _render_title, opts
-
end
-
-
1
def specify_type_in_link! opts
-
37
return if opts[:known] || !voo.type
-
opts[:path] = { card: { type: voo.type } }
-
end
-
-
1
view(:codename, compact: true) { card.codename.to_s }
-
1
view(:id, compact: true) { card.id }
-
1
view(:type, compact: true) { card.type_name }
-
-
# DATE VIEWS
-
-
1
view(:created_at, compact: true) { date_view card.created_at }
-
1
view(:updated_at, compact: true) { date_view card.updated_at }
-
1
view(:acted_at, compact: true) { date_view card.acted_at }
-
-
1
def date_view date
-
if voo.variant
-
date.strftime voo.variant
-
else
-
time_ago_in_words date
-
end
-
end
-
-
# CONTENT VIEWS
-
-
1
view :raw do
-
251
structure_card&.content || _render_blank
-
end
-
-
1
def structure_card
-
251
return nil if voo.structure == true
-
251
voo.structure ? Card[voo.structure] : card
-
end
-
-
1
view :core, compact: true do
-
171
process_content _render_raw
-
end
-
-
1
view :content do
-
_render_core
-
end
-
-
1
view :open_content do
-
2
_render_core
-
end
-
-
1
view :one_line_content, compact: true do
-
with_nest_mode :compact do
-
Card::Content.smart_truncate _render_core
-
end
-
end
-
-
1
view :labeled_content, unknown: :mini_unknown do
-
render_core
-
end
-
-
1
view :titled_content, unknown: :blank do
-
render_core
-
end
-
-
1
view :blank, compact: true, perms: :none do
-
56
""
-
end
-
-
# note: content and open_content may look like they should be aliased to
-
# core, but it's important that they render core explicitly so that core view
-
# overrides work. the titled and labeled views below, however, are not
-
# intended for frequent override, so this shortcut is fine.
-
-
# NAME + CONTENT VIEWS
-
-
1
view :titled do
-
"#{card.name}\n\n#{_render_core}"
-
end
-
1
view :open, :titled
-
-
1
view :labeled do
-
"#{card.name}: #{_render_labeled_content}"
-
end
-
1
view :closed, :labeled
-
-
# SPECIAL VIEWS
-
-
1
view :array, cache: :never do
-
card.item_cards(limit: 0).map do |item_card|
-
subformat(item_card)._render_core
-
end.inspect
-
end
-
-
# DEPRECATED
-
1
view :naked do
-
Rails.logger.info "DEPRECATED: naked view (used with #{card.name} card)"
-
render_core
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/base.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (File)
-
#
-
1
module File;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/file.rb"; end
-
2
module FileFormat; module_parent.send :register_set_format, Card::Format::FileFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
"File rendering of this card not yet supported"
-
end
-
-
1
view :style do
-
nil
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/file.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Head)
-
#
-
1
module Head;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/head.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :page_title, unknown: true, perms: :none do
-
23
title_parts = [Card::Rule.global_setting(:title)]
-
23
title_parts.unshift safe_name if card.name.present?
-
23
title_parts.join " - "
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# add tuples containing a
-
# - the codename of a card with javascript config (usually in json format)
-
# - the name of a javascript method that handles the config
-
1
basket :mod_js_config
-
-
1
view :head, unknown: true, perms: :none do
-
276
views_in_head.map { |viewname| render viewname }.flatten.compact.join "\n"
-
end
-
-
1
def views_in_head
-
23
%i[meta_tags page_title_tag favicon_tag head_stylesheet
-
decko_script_variables head_javascript html5shiv_tag
-
script_config_and_initiation
-
universal_edit_button rss_links]
-
end
-
-
# FIXME: tags not working with `template: :haml`
-
1
view :meta_tags, unknown: true, perms: :none do
-
23
haml :meta_tags
-
end
-
-
1
view :html5shiv_tag, unknown: true, perms: :none do
-
23
nest :script_html5shiv_printshiv, view: :script_tag
-
end
-
-
1
view :page_title_tag, unknown: true, perms: :none do
-
46
content_tag(:title) { render :page_title }
-
end
-
-
1
view :favicon_tag, unknown: true, perms: :none do
-
23
nest :favicon, view: :link_tag
-
end
-
-
1
view :universal_edit_button, unknown: true, denial: :blank, perms: :update do
-
15
return if card.new?
-
5
tag "link", rel: "alternate", type: "application/x-wiki",
-
title: "Edit this page!", href: path(view: :edit)
-
end
-
-
# these should render a view of the rule card
-
# it would then be safe to cache if combined with param handling
-
# (but note that machine clearing would need to reset card cache...)
-
1
view :head_stylesheet, unknown: true, cache: :never, perms: :none do
-
23
return unless (href = head_stylesheet_path)
-
23
tag "link", href: href, media: "all", rel: "stylesheet", type: "text/css"
-
end
-
-
1
view :head_javascript, unknown: true, cache: :never, perms: :none do
-
23
Array.wrap(head_javascript_paths).map do |path|
-
23
javascript_include_tag path
-
end
-
end
-
-
1
view :decko_script_variables, unknown: true, cache: :never, perms: :none do
-
23
string = ""
-
23
decko_script_variables.each do |k, v|
-
92
string += "#{k}=#{script_variable_to_js v};\n"
-
end
-
46
javascript_tag { string }
-
end
-
-
1
def decko_script_variables
-
{
-
23
"window.decko": { rootUrl: card_url("") },
-
"decko.doubleClick": Card.config.double_click,
-
"decko.cssPath": head_stylesheet_path,
-
23
"decko.currentUserId": (Auth.current_id if Auth.signed_in?)
-
-
}
-
end
-
-
1
def script_variable_to_js value
-
115
if value.is_a? Hash
-
23
string = "{"
-
46
value.each { |k, v| string += "#{k}:#{script_variable_to_js v}" }
-
23
string + "}"
-
else
-
92
"'#{value}'"
-
end
-
end
-
-
1
def param_or_rule_card setting
-
69
if params[setting]
-
Card[params[setting]]
-
else
-
69
root.card.rule_card setting
-
end
-
end
-
-
1
def debug_or_machine_path setting, &block
-
69
return unless (asset_card = param_or_rule_card setting)
-
69
debug_path(setting, asset_card, &block) || asset_card.machine_output_url
-
end
-
-
1
def debug_path setting, asset_card
-
69
return unless params[:debug] == setting.to_s
-
yield asset_card
-
end
-
-
1
def head_stylesheet_path
-
46
debug_or_machine_path :style do |style_card|
-
path mark: style_card.name, item: :import, format: :css
-
end
-
end
-
-
1
def head_javascript_paths
-
23
debug_or_machine_path :script do |script_card|
-
script_card.item_cards.map do |script|
-
script.format(:js).render :source
-
end
-
end
-
end
-
-
1
view :script_config_and_initiation, unknown: true, perms: :none do
-
23
javascript_tag do
-
23
(mod_js_configs << trigger_slot_ready).join "\n\n"
-
end
-
end
-
-
1
def mod_js_configs
-
23
mod_js_config.map do |codename, js_decko_function|
-
92
config_json = escape_javascript Card::Rule.global_setting(codename)
-
92
"decko.#{js_decko_function}('#{config_json}')"
-
end
-
end
-
-
1
def trigger_slot_ready
-
23
"$('document').ready(function() { $('.card-slot').trigger('slotReady'); })"
-
end
-
-
# TODO: move to rss mod
-
1
view :rss_links, unknown: true, perms: :none do
-
23
render :rss_link_tag if rss_link?
-
end
-
-
1
def rss_link?
-
23
Card.config.rss_enabled && respond_to?(:rss_link_tag)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/head.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Json)
-
#
-
1
module Json;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/json.rb"; end
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
# because card.item_cards returns "[[#{self}]]"
-
1
def item_cards
-
nested_cards
-
end
-
-
1
def default_nest_view
-
:atom
-
end
-
-
1
def default_item_view
-
params[:item] || :name
-
end
-
-
1
def max_depth
-
params[:max_depth].present? ? params[:max_depth].to_i : 1
-
end
-
-
# TODO: support layouts in json
-
# eg layout=stamp gives you the metadata currently in "page" view
-
# and layout=none gives you ONLY the requested view (default atom)
-
1
def show view, args
-
view ||= :molecule
-
raw = render! view, args
-
raw.is_a?(String) ? raw : stringify(raw)
-
end
-
-
1
def stringify raw
-
method = params[:compress] ? :generate : :pretty_generate
-
JSON.send method, raw
-
end
-
-
1
view :status, unknown: true, perms: :none do
-
status = card.state
-
hash = { key: card.key,
-
url_key: card.name.url_key,
-
status: status }
-
hash[:id] = card.id if status == :real
-
hash
-
end
-
-
# NOCACHE because of timestamp
-
1
view :page, cache: :never do
-
{ url: request_url,
-
timestamp: Time.now.to_s,
-
card: _render_atom }
-
end
-
-
1
def request_url
-
req = controller.request
-
req ? req.original_url : path
-
end
-
-
1
view :core, unknown: true do
-
card.known? ? render_content : nil
-
end
-
-
1
view :content do
-
card.content
-
end
-
-
1
view :nucleus do
-
nucleus
-
end
-
-
# TODO: add simple values for fields
-
1
view :atom, unknown: true do
-
atom
-
end
-
-
1
view :molecule do
-
molecule
-
end
-
-
# NOCACHE because sometimes item_cards is dynamic.
-
# could be safely cached for non-dynamic lists
-
1
view :items, cache: :never do
-
listing item_cards, view: :atom
-
end
-
-
1
view :links do
-
card.link_chunks.map do |chunk|
-
if chunk.referee_name
-
path mark: chunk.referee_name, format: :json
-
else
-
link_to_resource chunk.link_target
-
end
-
end
-
end
-
-
1
view :ancestors do
-
card.name.ancestors.map do |name|
-
nest name, view: :nucleus
-
end
-
end
-
-
# minimum needed to re-fetch card
-
1
view :cast do
-
card.cast
-
end
-
-
## DEPRECATED
-
1
view :marks do
-
{
-
id: card.id,
-
name: card.name,
-
key: card.key,
-
url: path
-
}
-
end
-
-
1
view :essentials do
-
if voo.show? :marks
-
render_marks.merge(essentials)
-
else
-
essentials
-
end
-
end
-
-
1
def essentials
-
return {} if card.structure
-
{ content: card.db_content }
-
end
-
-
# NOTE: moving these to methods prevents potential caching problems, because other
-
# views manipulate their hashes.
-
#
-
1
def nucleus
-
h = { id: card.id,
-
name: card.name,
-
type: card.type_name,
-
url: path(format: :json) }
-
h[:codename] = card.codename if card.codename
-
h
-
end
-
-
1
def atom
-
h = nucleus
-
h[:content] = render_content if card.known? && !card.structure
-
h
-
end
-
-
1
def molecule
-
atom.merge items: _render_items,
-
links: _render_links,
-
ancestors: _render_ancestors,
-
html_url: path,
-
type: nest(card.type_card, view: :nucleus)
-
end
-
end
-
-
# TODO: perhaps this should be in a general "data" module.
-
1
def cast
-
real? ? { id: id } : { name: name, type_id: type_id, content: db_content }
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/json.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Rss)
-
#
-
1
module Rss;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/rss.rb"; end
-
2
module RssFormat; module_parent.send :register_set_format, Card::Format::RssFormat, self; extend Card::Set::AbstractFormat
-
1
attr_accessor :xml
-
-
1
def initialize card, args
-
super
-
@xml = @parent ? @parent.xml : ::Builder::XmlMarkup.new
-
end
-
-
1
def show view, args
-
view ||= :feed
-
render! view, args
-
end
-
-
# FIXME: integrate this with common XML features when it is added
-
1
view :feed, cache: :never do
-
return "RSS feeds disabled" unless Cardio.config.rss_enabled
-
begin
-
@xml.instruct! :xml, version: "1.0", standalone: "yes"
-
@xml.rss version: "2.0",
-
"xmlns:content" => "http://purl.org/rss/1.0/modules/content/" do
-
@xml.channel do
-
@xml.title render_feed_title
-
@xml.description render_feed_description
-
@xml.link render_url
-
render_feed_body
-
end
-
end
-
rescue => e
-
@xml.error "\n\nERROR rendering RSS: #{e.inspect}\n\n #{e.backtrace}"
-
end
-
end
-
-
1
def raw_feed_items
-
[card]
-
end
-
-
1
view :feed_body, cache: :never do
-
raw_feed_items.each do |item|
-
@xml.item do
-
subformat(item).render! :feed_item
-
end
-
end
-
end
-
-
1
view :feed_title do
-
Card::Rule.global_setting(:title) + " : " + card.name.gsub(/^\*/, "")
-
end
-
-
1
view :feed_item do
-
@xml.title card.name
-
add_name_context
-
@xml.description render_feed_item_description
-
@xml.pubDate pub_date
-
@xml.link render_url
-
@xml.guid render_url
-
end
-
-
1
def pub_date
-
(card.updated_at || Time.zone.now).to_s(:rfc822)
-
# updated_at fails on virtual
-
# cards, because not all to_s's take args (just actual dates)
-
end
-
-
1
view :feed_item_description do
-
render_open_content
-
end
-
-
1
view(:feed_description) { "" }
-
1
view(:comment_box) { "" }
-
1
view(:menu) { "" }
-
-
1
view :open, :titled, mod: All::Base::Format
-
1
view :content, :core, mod: All::Base::Format
-
1
view :open_content, :core, mod: All::Base::Format
-
1
view :closed, :link, mod: All::Base::Format
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/rss.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Text)
-
#
-
1
module Text;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/all/text.rb"; end
-
-
2
module TextFormat; module_parent.send :register_set_format, Card::Format::TextFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
4
HTMLEntities.new.decode strip_tags(super()).to_s
-
# need this string method to get out of html_safe mode
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/all/text.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Head"
-
#
-
1
module Head;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/self/head.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# when *head is rendered in the main body of a page, we escape the HTML
-
# otherwise (most typically in the head tag, of course), we render the
-
# HTML unescaped
-
1
view :core, cache: :never do
-
23
escape_in_main do
-
23
nest root.card, view: :head
-
# note that the head tag for each card is different
-
# (different title, different style rules, etc)
-
# so we don't cache the core of *head, but we _do_ cache some
-
# views within each head (see all/head.rb)
-
end
-
end
-
-
1
view :input do
-
"Content can't be edited."
-
end
-
-
1
def escape_in_main
-
23
main? ? (h yield) : yield
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/self/head.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Html" cards
-
#
-
1
module Html;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/type/html.rb"; end
-
1
def clean_html?
-
false
-
end
-
-
1
def diff_args
-
{ diff_format: :raw }
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :one_line_content do
-
raw_one_line_content
-
end
-
-
1
def chunk_list
-
115
:references
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:ace_editor
-
end
-
-
1
view :one_line_content, wrap: {} do
-
raw_one_line_content
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/type/html.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Json" cards
-
#
-
# include_set Abstract::Pointer
-
1
module Json;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/type/json.rb"; end
-
-
1
event :validate_json, :validate, on: :save, changed: :content do
-
10
check_json_syntax if content.present?
-
end
-
-
1
def check_json_syntax
-
10
parse_content
-
rescue JSON::ParserError => e
-
errors.add tr(:invalid_json), e.message.sub(/^\d+: /, "").to_s
-
end
-
-
1
def parse_content
-
10
JSON.parse content
-
end
-
-
1
def item_names _args={}
-
parse_content.keys.map(&:to_name)
-
end
-
-
1
def item_values
-
parse_content.values
-
end
-
-
1
def item_value name
-
parse_content[name]
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
process_content ::CodeRay.scan(_render_raw, :json).div
-
end
-
-
1
def input_type
-
:ace_editor
-
end
-
-
1
def ace_mode
-
:json
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/type/json.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "PlainText" cards
-
#
-
1
module PlainText;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-format/set/type/plain_text.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:text_area
-
end
-
-
1
view :core do
-
process_content CGI.escapeHTML(_render_raw)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-format/set/type/plain_text.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (PagingParams)
-
#
-
1
module PagingParams;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/00_paging_params.rb"; end
-
1
MAX_ANONYMOUS_SEARCH_PARAM = 1000
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def limit_param
-
1
@limit ||= contextual_param(:limit) || default_limit
-
end
-
-
1
def offset_param
-
1
@offset ||= contextual_param(:offset) || 0
-
end
-
-
1
def contextual_param param
-
2
env_search_param(param) || voo_search_param(param)
-
end
-
-
1
def env_search_param param
-
2
return unless focal? && Env.params[param].present?
-
-
legal_search_param! param, Env.params[param].to_i
-
end
-
-
1
def legal_search_param! param, val
-
return val if Card::Auth.signed_in? || val <= MAX_ANONYMOUS_SEARCH_PARAM
-
-
raise Card::Error::PermissionDenied, "#{param} parameter exceeds maximum"
-
end
-
-
1
def voo_search_param param
-
2
voo&.cql&.dig param
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/00_paging_params.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Paging)
-
#
-
1
module Paging;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/01_paging.rb"; end
-
1
include_set Abstract::PagingParams
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def limit
-
limit_param
-
end
-
-
1
def offset
-
offset_param
-
end
-
-
1
def search_with_params
-
card.item_names
-
end
-
-
1
def count_with_params
-
card.item_names.count
-
end
-
-
1
def total_pages
-
return 1 if limit.zero?
-
((count_with_params - 1) / limit).to_i
-
end
-
-
1
def current_page
-
(offset / limit).to_i
-
end
-
-
# for override
-
1
def extra_paging_path_args
-
{}
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
PAGE_LI_CLASS = { ellipses: "disabled", current: "active" }.freeze
-
-
1
def with_paging path_args={}
-
with_paging_path_args path_args do
-
output [yield(@paging_path_args), _render_paging]
-
end
-
end
-
-
1
view :paging, cache: :never do
-
return "" unless paging_needed?
-
<<-HTML
-
<nav>
-
<ul class="pagination paging">
-
#{paging_links.join}
-
</ul>
-
</nav>
-
HTML
-
end
-
-
1
def paging_links
-
PagingLinks.new(total_pages, current_page)
-
.build do |text, page, status, options|
-
page_link_li text, page, status, options
-
end
-
end
-
-
# First page is 0 (not 1)
-
1
def page_link_li text, page, status, options={}
-
wrap_with :li, class: page_link_li_class(status) do
-
page_link text, page, options
-
end
-
end
-
-
1
def page_link_li_class status
-
["page-item", PAGE_LI_CLASS[status]].compact.join " "
-
end
-
-
1
def page_link text, page, options
-
return content_tag(:div, text.html_safe, class: "page-link") unless page
-
-
options.merge! class: "card-paging-link slotter page-link",
-
remote: true,
-
path: page_link_path_args(page)
-
link_to raw(text), options
-
end
-
-
1
def with_paging_path_args args
-
tmp = @paging_path_args
-
@paging_path_args = paging_path_args args
-
yield
-
ensure
-
@paging_path_args = tmp
-
end
-
-
1
def paging_path_args local_args={}
-
@paging_path_args ||= {}
-
@paging_path_args.reverse_merge!(limit: limit, offset: offset)
-
@paging_path_args.merge! extra_paging_path_args
-
@paging_path_args.merge local_args
-
end
-
-
1
def page_link_path_args page
-
paging_path_args.merge offset: page * limit
-
end
-
-
1
def paging_needed?
-
return false if limit < 1
-
return false if fewer_results_than_limit? # avoid extra count search
-
-
# count search result instead
-
limit < count_with_params
-
end
-
-
# clear we don't need paging even before running count query
-
1
def fewer_results_than_limit?
-
return false unless offset.zero?
-
-
limit > offset + search_with_params.length
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
def page_link_path_args page
-
{
-
limit: limit,
-
offset: page * limit,
-
item: default_item_view, # hack. need standard voo handling
-
format: :json
-
}.merge extra_paging_path_args
-
end
-
-
1
view :paging_urls, cache: :never do
-
return {} unless total_pages > 1
-
-
{ paging: paging_urls_hash }
-
end
-
-
1
def paging_urls_hash
-
hash = {}
-
PagingLinks.new(total_pages, current_page)
-
.build do |_text, page, status, _options|
-
add_paging_url hash, page, status
-
end
-
hash
-
end
-
-
1
def add_paging_url hash, page, status
-
return unless page && status.in?(%i[next previous])
-
-
hash[status] = path page_link_path_args(page)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/01_paging.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Paging)
-
#
-
#! no set module
-
-
1
module Paging;
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/01_paging/paging_links.rb"; end
-
# render paging links
-
1
class PagingLinks
-
1
def initialize total_pages, current_page
-
@total = total_pages
-
@current = current_page
-
end
-
-
# @param window [integer] number of page links shown left and right
-
# of the current page
-
# @example: current page = 5, window = 2
-
# |<<|1|...|3|4|[5]|6|7|...|10|>>|
-
# @yield [text, page, status, options] block to build single paging link
-
# @yieldparam status [Symbol] :active (for current page) or :disabled
-
# @yieldparam page [Integer] page number, first page is 0
-
# @return [Array<String>]
-
1
def build window=2, &block
-
@render_item = block
-
links window
-
end
-
-
1
private
-
-
1
def links window
-
@window_start = [@current - window, 0].max
-
@window_end = [@current + window, @total].min
-
left_part + window_part + right_part
-
end
-
-
# the links around the current page
-
1
def window_part
-
(@window_start..@window_end).map do |page|
-
direct_page_link page
-
end.compact
-
end
-
-
1
def left_part
-
[
-
previous_page_link,
-
(direct_page_link 0 if @window_start > 0),
-
(ellipse if @window_start > 1)
-
].compact
-
end
-
-
1
def right_part
-
[
-
(ellipse if @total > @window_end + 1),
-
(direct_page_link @total if @total > @window_end),
-
next_page_link
-
].compact
-
end
-
-
1
def previous_page_link
-
paging_item '<span aria-hidden="true">«</span>', previous_page,
-
"aria-label" => "Previous", status: :previous
-
end
-
-
1
def next_page_link
-
paging_item '<span aria-hidden="true">»</span>', next_page,
-
"aria-label" => "Next", status: :next
-
end
-
-
1
def direct_page_link page
-
return unless page >= 0 && page <= @total
-
paging_item page + 1, page
-
end
-
-
1
def ellipse
-
paging_item "<span>...</span>", nil, status: :ellipses
-
end
-
-
1
def paging_item text, page, options={}
-
status =
-
if page == @current
-
:current
-
else
-
options.delete :status
-
end
-
@render_item.call text, page, status, options
-
end
-
-
1
def previous_page
-
@current > 0 ? @current - 1 : false
-
end
-
-
1
def next_page
-
@current < @total ? @current + 1 : false
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/01_paging/paging_links.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Items)
-
#
-
# ~~~~~~~~~~~~ READING ITEMS ~~~~~~~~~~~~
-
-
1
module Items;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_items.rb"; end
-
# While each of the three main methods for returning lists of items can handle arguments,
-
# they are most commonly used without them.
-
-
# @return [Array] list of Card::Name objects
-
# @param args [Hash]
-
# @option args [String] :content override card content
-
# @option args [String, Card::Name, Symbol] :context name in whose context relative items
-
# will be interpreted. For example. +A in context of B is interpreted as B+A
-
# context defaults to pointer card's name. If value is `:raw`, then name is not
-
# contextualized
-
# @option args [String, Integer] :limit max number of cards to return
-
# @option args [String, Integer] :offset begin after the offset-th item
-
1
def item_names args={}
-
1473
context = args[:context]
-
1473
item_strings(args).map do |item|
-
1826
clean_item_name item, context
-
end.compact
-
end
-
-
1
def first_name args={}
-
item_names(args).first
-
end
-
-
1
def first_card args={}
-
return unless (name = first_name)
-
fetch_item_card name, args
-
end
-
-
1
def first_code
-
first_card&.codename
-
end
-
-
# @return [Array] list of integers (card ids of items)
-
# @param args [Hash] see #item_names
-
1
def item_ids args={}
-
130
item_names(args).map { |name| Card.fetch_id name }.compact
-
end
-
-
# @return [Array] list of Card objects
-
# @param args [Hash] see #item_names for additional options
-
# @option args [String] :complete keyword to use in searching among items
-
# @option args [True/False] :known_only if true, return only known cards
-
# @option args [String] :type name of type to be used for unknown cards
-
1
def item_cards args={}
-
1311
return item_cards_search(args) if args[:complete]
-
1311
return known_item_cards(args) if args[:known_only]
-
1311
all_item_cards args
-
end
-
-
# #item_name, #item_id, and #item_card each return a single item, rather than an array.
-
1
%i[name id card].each do |obj|
-
3
define_method "item_#{obj}" do |args={}|
-
23
send("item_#{obj}s", args.merge(limit: 1)).first
-
end
-
end
-
-
# for override, eg by json
-
1
def item_value item_name
-
item_name
-
end
-
-
# ~~~~~~~~~~~~ ALTERING ITEMS ~~~~~~~~~~~~
-
-
# set card content based on array and save card
-
# @param array [Array] list of strings/names (Cardish)
-
1
def items= array
-
2
items_to_content array
-
2
save!
-
end
-
-
# append item to list (does not save)
-
# @param cardish [Cardish]
-
1
def << cardish
-
add_item cardish
-
end
-
-
# append item to list (does not save)
-
# @param cardish [String, Card::Name] item name
-
# @param allow_duplicates [True/False] permit duplicate items (default is False)
-
1
def add_item cardish, allow_duplicates=false
-
return if !allow_duplicates && include_item?(cardish)
-
-
items = item_strings << cardish
-
items_to_content items
-
end
-
-
# append item to list and save card
-
# @param name [String, Card::Name] item name
-
1
def add_item! name
-
add_item(name) && save!
-
end
-
-
# remove item from list
-
# @param cardish [String, Card::Name] item to drop
-
1
def drop_item cardish
-
drop_item_name = Card::Name[cardish]
-
items_to_content(item_names.reject { |item_name| item_name == drop_item_name })
-
end
-
-
# remove item from list and save card
-
# @param cardish [String, Card::Name] item to drop
-
1
def drop_item! cardish
-
drop_item cardish
-
save!
-
end
-
-
# insert item into list at specified location
-
# @param index [Integer] Array index in which to insert item (0 is first)
-
# @param name [String, Card::Name] item name
-
1
def insert_item index, name
-
10
new_names = item_names
-
10
new_names.delete name
-
10
new_names.insert index, name
-
10
items_to_content new_names
-
end
-
-
# insert item into list at specified location and save
-
# @param index [Integer] Array index in which to insert item (0 is first)
-
# @param name [String, Card::Name] item name
-
1
def insert_item! index, name
-
insert_item index, name
-
save!
-
end
-
-
# ~~~~~~~~~~~~ READING ITEM HELPERS ~~~~~~~~~~~~
-
-
# Warning: the following methods, while available for use, may be subject to change
-
-
# #item_cards helpers
-
-
1
def item_cards_search query
-
Card::Query.run query.reverse_merge(referred_to_by: name, limit: 0)
-
end
-
-
1
def known_item_cards args={}
-
item_names(args).map { |name| Card.fetch name }.compact
-
end
-
-
1
def all_item_cards args={}
-
1311
names = args[:item_names] || item_names(args)
-
2632
names.map { |name| fetch_item_card name, args }
-
end
-
-
# TODO: support type_code and type_id. (currently type)
-
# uses name, because its most common use is from CQL
-
1
def item_type
-
1321
opt = options_rule_card
-
# FIXME: need better recursion prevention
-
1321
return if !opt || opt == self
-
1305
opt.item_type
-
end
-
-
1
def item_strings args={}
-
1481
items = raw_item_strings(args[:content] || content)
-
1481
return items unless args.present?
-
-
36
filtered_items items, args.slice(:limit, :offset)
-
end
-
-
1
def raw_item_strings content
-
3313
content.to_s.split(/\n+/).map { |i| strip_item i }
-
end
-
-
1
private
-
-
1
def filtered_items items, limit: 0, offset: 0
-
36
limit = limit.to_i
-
36
offset = offset.to_i
-
36
return items unless limit.positive? || offset.positive?
-
-
23
items[offset, (limit.zero? ? items.size : limit)] || []
-
end
-
-
1
def fetch_item_card name, args={}
-
1321
Card.fetch name, new: new_unknown_item_args(args)
-
end
-
-
1
def new_unknown_item_args args
-
1321
itype = args[:type] || item_type
-
1321
itype ? { type: itype } : {}
-
end
-
-
1
def clean_item_name item, context
-
1826
item = item.to_name
-
1826
return item if context == :raw
-
1826
context ||= context_card.name
-
1826
item.absolute_name context
-
rescue Card::Error::NotFound
-
# eg for invalid ids or codenames
-
# "Invalid Item: #{item}".to_name
-
nil
-
end
-
-
1
def strip_item item
-
1832
item.gsub(/\[\[|\]\]/, "").strip
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_items.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Pointer)
-
#
-
1
module Pointer;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer.rb"; end
-
1
include_set Abstract::Paging
-
1
include_set Abstract::Items
-
-
1
def diff_args
-
{ diff_format: :pointer }
-
end
-
-
1
def count
-
item_strings.size
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Pointer;
-
# Set: Abstract (Pointer, Events)
-
#
-
1
module Events;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/events.rb"; end
-
1
event :add_and_drop_items, :prepare_to_validate, on: :save do
-
35
adds = Env.params["add_item"]
-
35
drops = Env.params["drop_item"]
-
35
Array.wrap(adds).each { |i| add_item i } if adds
-
35
Array.wrap(drops).each { |i| drop_item i } if drops
-
end
-
-
1
event :insert_item_event, :prepare_to_validate, on: :save, when: :item_to_insert do
-
index = Env.params["item_index"] || 0
-
insert_item index.to_i, item_to_insert
-
end
-
-
1
def item_to_insert
-
35
Env.params["insert_item"]
-
end
-
-
# If a card's type and content are updated in the same action, the new module
-
# will override the old module's events and functions. But this event is only
-
# on pointers -- other type cards do not have this event,
-
# Therefore if something is changed from a pointer and its content is changed
-
# in the same action, this event will be run and will treat the content like
-
# it' still pointer content. The "when" clause helps with that (but is a hack)
-
1
event :standardize_items, :prepare_to_validate,
-
on: :save, changed: :content, when: :still_pointer? do
-
8
items_to_content item_strings
-
end
-
-
1
def still_pointer?
-
28
type_id == PointerID
-
# Card.new(type_id: type_id).is_a? Abstract::Pointer
-
end
-
-
1
def changed_item_names
-
dropped_item_names + added_item_names
-
end
-
-
1
def dropped_item_names
-
return item_names if trash
-
return [] unless (old_content = db_content_before_act)
-
-
old_items = item_names content: old_content
-
old_items - item_names
-
end
-
-
1
def added_item_names
-
return [] if trash
-
return item_names unless (old_content = db_content_before_act)
-
-
old_items = item_names content: old_content
-
item_names - old_items
-
end
-
-
# TODO: refactor. many of the above could be written more elegantly with improved
-
# handling of :content in item_names. If content is nil here, we would expect an
-
# empty set of cards, but in fact we get items based on self.content.
-
-
1
def changed_item_cards
-
dropped_item_cards + added_item_cards
-
end
-
-
1
def dropped_item_cards
-
return [] unless db_content_before_act
-
-
all_item_cards item_names: dropped_item_names
-
end
-
-
1
def added_item_cards
-
return item_cards unless db_content_before_act
-
-
all_item_cards item_names: added_item_names
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/events.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Pointer;
-
# Set: Abstract (Pointer, HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/html_views.rb"; end
-
1
include_set Abstract::BsBadge
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core, cache: :never do
-
standard_pointer_core
-
end
-
-
1
view :item_cores, cache: :never do
-
card.known_item_cards.map do |item|
-
nest item, view: :core
-
end.join "\n"
-
end
-
-
1
def standard_pointer_core
-
with_paging do |paging_args|
-
wrap_with :div, standard_pointer_items(paging_args), class: "pointer-list"
-
end
-
end
-
-
1
def standard_pointer_items paging_args
-
pointer_items(paging_args.extract!(:limit, :offset)).join(voo.separator || "\n")
-
end
-
-
1
view :one_line_content do
-
item_view = implicit_item_view
-
item_view = item_view == "name" ? "name" : "link"
-
wrap_with :div, class: "pointer-list" do
-
# limit to first 10 items to optimize
-
pointer_items(view: item_view, limit: 10, offset: 0).join ", "
-
end
-
end
-
-
1
def wrap_item rendered, item_view
-
%(<div class="pointer-item item-#{item_view}">#{rendered}</div>)
-
end
-
-
1
view :input do
-
12
_render_hidden_content_field + super()
-
end
-
-
1
def default_input_type
-
:list
-
end
-
-
1
view :list, cache: :never do
-
list_input
-
end
-
-
# view :nav_item do
-
# nav_dropdown
-
# end
-
-
1
def list_input args={}
-
items = items_for_input args[:item_list]
-
extra_class = "pointer-list-ul"
-
ul_classes = classy "pointer-list-editor", extra_class
-
haml :list_input, items: items, ul_classes: ul_classes,
-
options_card: options_card_name
-
end
-
-
1
%i[autocomplete checkbox radio select multiselect].each do |editor_view|
-
5
view(editor_view) { send "#{editor_view}_input" }
-
end
-
-
1
def autocomplete_input
-
items = items_for_input
-
haml :autocomplete_input, item: items.first, options_card: options_card_name
-
end
-
-
1
def checkbox_input
-
haml :checkbox_input, submit_on_change: @submit_on_change
-
end
-
-
1
def radio_input
-
haml :radio_input, submit_on_change: @submit_on_change
-
end
-
-
1
def select_input
-
options = { "-- Select --" => "" }.merge card.options_hash
-
select_tag("pointer_select-#{unique_id}",
-
options_for_select(options, card.item_name),
-
class: "pointer-select form-control")
-
end
-
-
1
def multiselect_input
-
select_tag "pointer_multiselect-#{unique_id}",
-
options_for_select(card.options_hash, card.item_names),
-
multiple: true, class: "pointer-multiselect form-control"
-
end
-
-
1
def add_item_modal_link
-
modal_link "Add Item",
-
size: :large,
-
class: "btn btn-sm btn-outline-secondary _add-item-link",
-
path: { view: :filter_items_modal,
-
item: implicit_item_view,
-
filter_card: filter_card.name,
-
slot_selector: filtered_list_slot_class,
-
item_selector: "_filtered-list-item",
-
slot: { hide: [:modal_footer] },
-
filter: { not_ids: not_ids_value } }
-
end
-
-
1
def not_ids_value
-
card.item_ids.map(&:to_s).join(",")
-
end
-
-
1
def add_item_overlay_link; end
-
-
1
def one_line_content
-
if count == 1
-
card.first_name
-
else
-
short_content
-
end
-
end
-
-
1
private
-
-
# currently only used by :list and :autocomplete. could be generalized?
-
1
def items_for_input items=nil
-
items ||= card.item_names context: :raw
-
items.empty? ? [""] : items
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class Abstract; module Pointer;; module HtmlViews;
-
# Set: Abstract (Pointer, HtmlViews, Filter)
-
#
-
1
module Filter;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/html_views/filter.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :filtered_list, unknown: true do
-
filtered_list_input
-
end
-
-
1
view :filter_items_modal, unknown: true, wrap: :modal do
-
render_filter_items
-
end
-
-
1
view :filter_items, unknown: true, wrap: :slot, template: :haml
-
-
1
def filtered_list_input
-
with_nest_mode :normal do
-
class_up "card-slot", filtered_list_slot_class
-
with_class_up "card-slot", filtered_list_slot_class do
-
wrap do
-
haml :filtered_list_input
-
end
-
end
-
end
-
end
-
-
# NOCACHE because params alter view
-
1
view :add_selected_link, cache: :never, unknown: true do
-
link_to "Add Selected",
-
path: { filter_card: params[:filter_card] },
-
class: "_add-selected slotter _close-modal btn btn-primary disabled",
-
data: { "slot-selector": ".#{params[:slot_selector]}",
-
"item-selector": ".#{params[:item_selector]}",
-
remote: true }
-
end
-
-
1
def filtered_list_item item_card
-
nest_item item_card do |rendered, item_view|
-
wrap_item rendered, item_view
-
end
-
end
-
-
# for override
-
# @return [Card] search card on which filtering is based
-
1
def filter_card
-
filter_card_from_params || default_filter_card
-
end
-
-
1
def default_filter_card
-
fcard = card.options_rule_card || Card[:all]
-
return fcard if fcard.respond_to? :cql_hash
-
-
fcard.fetch :referred_to_by, new: {}
-
end
-
-
1
def filter_card_from_params
-
return unless params[:filter_card]
-
Card.fetch params[:filter_card], new: {}
-
end
-
-
# currently actually used as a class
-
# (because we don't have api to override slot's id)
-
1
def filtered_list_slot_class
-
@filtered_list_slot_class ||= "filtered-list-#{unique_id}"
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/html_views/filter.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Pointer;
-
# Set: Abstract (Pointer, OptionsApi)
-
#
-
# TODO: some of this should be moved to right/options!!
-
1
module OptionsApi;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/options_api.rb"; end
-
# or to type/JSON?
-
-
1
def options_hash
-
json_options? ? options_card.parse_content : option_hash_from_names
-
end
-
-
1
def json_options?
-
options_card&.type_id == JsonID
-
end
-
-
1
def option_hash_from_names
-
option_names.each_with_object({}) do |name, hash|
-
hash[name] = name
-
end
-
end
-
-
1
def option_names
-
if (selected_options = item_names)
-
(standard_option_names + selected_options).uniq
-
else
-
standard_option_names
-
end
-
end
-
-
1
def option_cards
-
option_names.map do |name|
-
Card.fetch name, new: {}
-
end
-
end
-
-
1
def options_rule_card
-
20
rule_card :content_options
-
end
-
-
1
def standard_option_names
-
if json_options?
-
options_hash.values.map(&:to_name)
-
else
-
option_names_from_items
-
end
-
end
-
-
1
def option_names_from_items
-
o_card = options_card
-
limit = o_card.try(:default_limit).to_i
-
o_card.item_names context: name, limit: limit
-
end
-
-
1
def options_card
-
options_rule_card || Card[:all]
-
end
-
-
1
def options_card_name
-
options_rule_card&.name&.url_key || ":all"
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def options_card_name
-
card.options_card_name
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def option_label option_name, id
-
%(<label for="#{id}">#{option_label_text option_name}</label>)
-
end
-
-
1
def option_view
-
@option_view ||= card.rule(:content_option_view) || :smart_label
-
end
-
-
1
def option_label_text option_name
-
return option_name unless (option_card = Card.fetch option_name)
-
-
nest option_card, view: option_view
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/options_api.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Pointer;
-
# Set: Abstract (Pointer, OtherViews)
-
#
-
# BASE views
-
1
module OtherViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/other_views.rb"; end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def default_limit
-
20
-
end
-
-
1
def item_links args={}
-
card.item_cards(args).map do |item_card|
-
subformat(item_card).render_link
-
end
-
end
-
-
1
def nest_item_array
-
card.item_cards.map do |item|
-
nest_item item
-
end
-
end
-
-
1
view :core do
-
pointer_items.join ", "
-
end
-
-
1
def pointer_items args={}
-
page_args = args.extract! :limit, :offset
-
listing card.item_cards(page_args), args
-
end
-
end
-
-
# JavaScript views
-
-
2
module JsFormat; module_parent.send :register_set_format, Card::Format::JsFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
nest_item_array.join "\n\n"
-
end
-
end
-
-
# Data views
-
-
2
module DataFormat; module_parent.send :register_set_format, Card::Format::DataFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
nest_item_array
-
end
-
end
-
-
# JSON views
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
view :content do
-
card.item_names
-
end
-
-
1
def item_cards
-
card.item_cards
-
end
-
-
1
def max_depth
-
params[:max_depth] || 1
-
end
-
-
1
def items_for_export
-
card.item_cards
-
end
-
-
1
def essentials
-
return {} if depth > max_depth
-
card.item_cards.map do |item|
-
nest item, view: :essentials
-
end
-
end
-
-
1
view :links do
-
[]
-
end
-
end
-
-
# CSS views
-
-
2
module CssFormat; module_parent.send :register_set_format, Card::Format::CssFormat, self; extend Card::Set::AbstractFormat
-
# generalize to all collections?
-
1
def default_item_view
-
:content
-
end
-
-
1
view :titled do
-
%(#{major_comment "STYLE GROUP: \"#{card.name}\"", '='}#{_render_core})
-
end
-
-
1
view :core do
-
nest_item_array.join "\n\n"
-
end
-
-
1
view :content, :core
-
end
-
-
# RSS views
-
-
2
module RssFormat; module_parent.send :register_set_format, Card::Format::RssFormat, self; extend Card::Set::AbstractFormat
-
1
def raw_feed_items
-
@raw_feed_items ||= card.item_cards(limit: limit, offset: offset)
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/02_pointer/other_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (CodePointer)
-
#
-
1
module CodePointer;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/code_pointer.rb"; end
-
1
include_set Abstract::Pointer
-
-
1
abstract_basket :item_codenames
-
-
# simplify api
-
# Self::MyCodePointerSet.add_item :my_item_codename
-
# instead of
-
# Self::MyCodePointerSet.add_to_basket :item_codenames, :my_item_codename
-
1
module ClassMethods
-
1
def add_item codename
-
21
valid_codename codename do
-
21
add_to_basket :item_codenames, codename
-
end
-
end
-
-
1
def unshift_item codename
-
valid_codename codename do
-
unshift_basket :item_codenames, codename
-
end
-
end
-
-
1
def valid_codename codename
-
21
if Card::Codename.exist? codename
-
21
yield
-
else
-
Rails.logger.info "unknown codename '#{codename}' added to code pointer"
-
end
-
end
-
end
-
-
1
def content
-
4
item_codenames.map do |codename|
-
14
Card.fetch_name codename
-
end.compact.to_pointer_content
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/code_pointer.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (IdPointer)
-
#
-
# store items as ids, not names
-
1
module IdPointer;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/id_pointer.rb"; end
-
-
1
def standardize_item cardish
-
if (id = Card.fetch_id cardish)
-
"~#{id}"
-
else
-
Rails.logger.info "no id for '#{cardish}' added to id pointer"
-
nil
-
end
-
end
-
-
1
def item_ids args={}
-
item_strings(args).map do |item|
-
item = standardize_item item unless item.match?(/^~/)
-
item.to_s.tr("~", "").to_i
-
end.compact
-
end
-
-
1
def item_names args={}
-
item_ids(args).map(&:cardname).compact
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/abstract/id_pointer.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+ContentOptions" cards
-
#
-
1
module ContentOptions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/right/content_options.rb"; end
-
1
def default_limit
-
cql_limit = fetch_query.limit if respond_to?(:fetch_query)
-
cql_limit || 50
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/right/content_options.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "InputOptions"
-
#
-
1
module InputOptions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/input_options.rb"; end
-
1
include_set Abstract::Pointer
-
-
1
basket :options
-
1
add_to_basket :options, "radio"
-
1
add_to_basket :options, "checkbox"
-
1
add_to_basket :options, "select"
-
1
add_to_basket :options, "multiselect"
-
1
add_to_basket :options, "list"
-
1
add_to_basket :options, "filtered list"
-
-
1
def content
-
options.to_pointer_content
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/input_options.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptEditors"
-
#
-
1
module ScriptEditors;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_editors.rb"; end
-
1
include_set Abstract::CodePointer
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_editors.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptLibraries"
-
#
-
1
module ScriptLibraries;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_libraries.rb"; end
-
1
include_set Abstract::CodePointer
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_libraries.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptMods"
-
#
-
1
module ScriptMods;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_mods.rb"; end
-
1
include_set Abstract::CodePointer
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_mods.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptPointerConfig"
-
#
-
1
module ScriptPointerConfig;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_pointer_config.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
FILE_NAMES = %w[pointer_config pointer_list_editor]
-
-
1
def source_files
-
coffee_files FILE_NAMES
-
end
-
-
1
Self::ScriptEditors.add_item :script_pointer_config
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/script_pointer_config.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleLibraries"
-
#
-
1
module StyleLibraries;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/style_libraries.rb"; end
-
1
include_set Abstract::CodePointer
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/style_libraries.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleMods"
-
#
-
1
module StyleMods;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/style_mods.rb"; end
-
1
include_set Abstract::CodePointer
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/self/style_mods.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "LinkList" cards
-
#
-
1
module LinkList;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/link_list.rb"; end
-
1
include_set Abstract::Pointer
-
-
1
def raw_item_strings content
-
reference_chunks(content).map(&:referee_name)
-
end
-
-
1
def item_titles default_to_name=true
-
reference_chunks.map do |chunk|
-
chunk.options[:title] || (default_to_name ? chunk.referee_name : nil)
-
end
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def chunk_list
-
:references
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:link_list
-
end
-
-
1
view :link_list_input, cache: :never do
-
link_list_input
-
end
-
-
1
def items_for_input items=nil
-
items ||= card.item_names context: :raw
-
items.empty? ? [["", ""]] : items.zip(card.item_titles(false))
-
end
-
-
1
def link_list_input args={}
-
items = items_for_input args[:item_list]
-
extra_class = "pointer-link-list-ul"
-
ul_classes = classy "pointer-list-editor", extra_class
-
haml :link_list_input, items: items, ul_classes: ul_classes,
-
options_card: options_card_name
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/link_list.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "List" cards
-
#
-
1
module List;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/list.rb"; end
-
1
include_set Abstract::Pointer
-
-
1
def each_reference_out
-
18
item_names.each do |name|
-
147
yield(name, Card::Content::Chunk::Link::CODE)
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :view_list do
-
%i[info_bar bar box closed titled labeled].map do |view|
-
voo.items[:view] = view
-
wrap_with :p, [content_tag(:h3, "#{view} items"), render_content]
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/list.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "MirrorList" cards
-
#
-
1
module MirrorList;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/mirror_list.rb"; end
-
1
include_set Abstract::Pointer
-
-
1
event :validate_listed_by_name, :validate, on: :save, changing: :name do
-
if !junction? || !right || right.type_id != Card::CardtypeID
-
errors.add :name, tr(:cardtype_right)
-
end
-
end
-
-
1
event :validate_listed_by_content, :validate,
-
on: :save, changing: :content do
-
item_cards(content: content).each do |item_card|
-
next unless item_card.type_id != right.id
-
errors.add(
-
:content,
-
"#{item_card.name} has wrong cardtype; " \
-
"only cards of type #{name.right} are allowed"
-
)
-
end
-
end
-
-
1
event :update_content_in_list_cards, :prepare_to_validate,
-
on: :save, changing: :content do
-
return unless db_content.present?
-
new_items = item_keys(content: db_content)
-
old_items = item_keys(content: old_content)
-
remove_items(old_items - new_items)
-
add_items(new_items - old_items)
-
end
-
-
1
def old_content
-
db_content_before_act.present? ? db_content_before_act : content_cache.read(key)
-
end
-
-
1
def remove_items items
-
items.each do |item|
-
next unless (lc = list_card item)
-
lc.drop_item name.left
-
subcards.add lc
-
end
-
end
-
-
1
def add_items items
-
items.each do |item|
-
if (lc = list_card(item))
-
lc.add_item name.left
-
subcards.add lc
-
else
-
subcards.add(name: "#{Card[item].name}+#{left.type_name}",
-
type: "list",
-
content: "[[#{name.left}]]")
-
end
-
end
-
end
-
-
1
def content_cache
-
Card::Cache[Card::Set::Type::MirrorList]
-
end
-
-
1
def content
-
content_cache.fetch(key) do
-
generate_content
-
end
-
end
-
-
1
def generate_content
-
listed_by.map do |item|
-
"[[%s]]" % item.to_name.left
-
end.join "\n"
-
end
-
-
1
def listed_by
-
Card.search(
-
{ type_id: Card::MirroredListID, right: trunk.type_name,
-
left: { type: name.tag }, refer_to: name.trunk, return: :name },
-
"all cards listed by #{name}"
-
)
-
end
-
-
1
def update_cached_list
-
if trunk
-
Card::Cache[Card::Set::Type::MirrorList].write key, generate_content
-
else
-
Card::Cache[Card::Set::Type::MirrorList].delete key
-
end
-
end
-
-
1
def list_card item
-
Card.fetch item, left.type_name
-
end
-
-
1
def unfilled?
-
false
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/mirror_list.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "MirroredList" cards
-
#
-
1
module MirroredList;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/mirrored_list.rb"; end
-
1
include_set Abstract::Pointer
-
-
1
event :validate_list_name, :validate, on: :save, changed: :name do
-
errors.add :name, tr(:cardtype_right) unless right&.type_id == Card::CardtypeID
-
end
-
-
1
event :validate_list_item_type_change, :validate,
-
on: :save, changed: :name do
-
item_cards.each do |item_card|
-
next unless item_card.type_name.key != item_type_name.key
-
errors.add :name, tr(:conflict_item_type)
-
end
-
end
-
-
1
event :validate_list_content, :validate,
-
on: :save, changed: :content do
-
item_cards.each do |item_card|
-
next unless item_card.type_name.key != item_type_name.key
-
errors.add :content, tr(
-
:only_type_allowed,
-
cardname: item_card.name,
-
cardtype: name.right
-
)
-
end
-
end
-
-
1
event :create_listed_by_cards, :prepare_to_validate,
-
on: :save, changed: :content do
-
item_names.each do |item_name|
-
listed_by_name = "#{item_name}+#{left.type_name}"
-
next if director.main_director.card.key == listed_by_name.to_name.key
-
if !Card[listed_by_name]
-
add_subcard listed_by_name, type_id: Card::MirrorListID
-
else
-
Card[listed_by_name].update_references_out
-
end
-
end
-
end
-
-
1
event :update_related_listed_by_card_on_create, :finalize,
-
on: :create do
-
update_listed_by_cache_for item_keys
-
end
-
-
1
event :update_related_listed_by_card_on_content_update, :finalize,
-
on: :update, changed: :content do
-
new_items = item_keys
-
changed_items =
-
if db_content_before_act
-
old_items = item_keys(content: db_content_before_act)
-
old_items + new_items - (old_items & new_items)
-
else
-
new_items
-
end
-
update_listed_by_cache_for changed_items
-
end
-
-
1
event :update_related_listed_by_card_on_name_and_type_changes, :finalize,
-
on: :update, changed: %i[name type_id] do
-
update_all_items
-
end
-
-
1
event :update_related_listed_by_card_on_delete, :finalize,
-
on: :delete, when: proc { |c| c.junction? } do
-
update_listed_by_cache_for item_keys, type_key: @left_type_key
-
end
-
-
1
event :cache_type_key, :store,
-
on: :delete, when: proc { |c| c.junction? } do
-
@left_type_key = left.type_card.key
-
end
-
-
1
def update_all_items
-
current_items = item_keys
-
if db_content_before_act
-
old_items = item_keys(content: db_content_before_act)
-
update_listed_by_cache_for old_items
-
end
-
update_listed_by_cache_for current_items
-
end
-
-
1
def update_listed_by_cache_for item_keys, args={}
-
type_key = args[:type_key] || left&.type_card&.key
-
return unless type_key
-
-
item_keys.each do |item_key|
-
key = "#{item_key}+#{type_key}"
-
next unless Card::Cache[Card::Set::Type::MirrorList].exist? key
-
if (card = Card.fetch(key)) && card.left
-
card.update_cached_list
-
card.update_references_out
-
else
-
Card::Cache[Card::Set::Type::MirrorList].delete key
-
end
-
end
-
end
-
-
1
def item_type
-
name.right
-
end
-
-
1
def item_type_name
-
name.right_name
-
end
-
-
1
def item_type_card
-
name.right
-
end
-
-
1
def item_type_id
-
right.id
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/mirrored_list.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "NestList" cards
-
#
-
1
module NestList;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/nest_list.rb"; end
-
1
include_set Abstract::Items
-
-
1
def raw_item_strings content
-
reference_chunks(content).map(&:referee_name)
-
end
-
-
1
def item_options
-
nest_chunks.map(&:raw_options)
-
end
-
-
1
def items_to_content array
-
items = array.map { |i| standardize_item i }.reject(&:blank?)
-
self.content = items.join("\n")
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def chunk_list
-
:references
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:nest_list
-
end
-
-
1
view :nest_list_input, cache: :never do
-
nest_list_input
-
end
-
-
1
view :input do
-
_render_hidden_content_field + super()
-
end
-
-
1
def items_for_input items=nil
-
items ||= card.item_names context: :raw
-
items.empty? ? [["", ""]] : items.zip(card.item_options)
-
end
-
-
1
def nest_list_input args={}
-
items = items_for_input args[:item_list]
-
extra_class = "_nest-list-ul"
-
ul_classes = classy "pointer-list-editor", extra_class
-
haml :nest_list_input, items: items, ul_classes: ul_classes
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/nest_list.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Pointer" cards
-
#
-
1
module Pointer;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/pointer.rb"; end
-
1
include_set Abstract::Pointer
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :view_list do
-
%i[info_bar bar box closed titled labeled].map do |view|
-
voo.items[:view] = view
-
wrap_with :p, [content_tag(:h3, "#{view} items"), render_content]
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/pointer/set/type/pointer.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (VirtualCache)
-
#
-
# -*- encoding : utf-8 -*-
-
1
module VirtualCache;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-virtual/set/abstract/virtual_cache.rb"; end
-
-
1
def virtual?
-
2
new?
-
end
-
-
1
def history?
-
1
false
-
end
-
-
1
def followable?
-
false
-
end
-
-
1
def db_content
-
2
Card::Virtual.fetch_content(self)
-
end
-
-
# called to refresh the virtual content
-
# the default way is to use the card's template content
-
1
def generate_virtual_content
-
1
template&.db_content
-
end
-
-
1
event :save_virtual_content, :prepare_to_store, on: :save, changed: :content do
-
1
Card::Virtual.create_or_update(self, attributes["db_content"])
-
1
abort :success
-
end
-
-
1
event :delete_virtual_content, :prepare_to_store, on: :delete do
-
Card::Virtual.find_by_card(self)&.delete
-
abort :success
-
end
-
-
1
def delete
-
# delete although it's new
-
update trash: true
-
end
-
-
1
def delete!
-
# delete although it's new
-
update! trash: true
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-virtual/set/abstract/virtual_cache.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Machine)
-
#
-
# ## What are Machines?
-
# {Machine} and {MachineInput} together implement a kind of observer pattern.
-
# {Machine} processes a collection of input cards to generate an output card
-
# (a {Set::Type::File} card by default). If one of the input cards is changed
-
# the output card will be updated.
-
#
-
# The classic example: A style card observes a collection of css and sccs card
-
# to generate a file card with a css file that contains the assembled
-
# compressed css.
-
#
-
# ## Using Machines
-
# Include the Machine module in the card set that is supposed to produce the
-
# output card. If the output card should be automatically updated when a input
-
# card is changed the input card has to be in a set that includes the
-
# MachineInput module.
-
#
-
# The default machine:
-
1
module Machine;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine.rb"; end
-
#
-
# - uses its item cards as input cards or the card itself if there are no
-
# item cards;
-
# - can be changed by passing a block to collect_input_cards
-
# - takes the raw view of the input cards to generate the output;
-
# - can be changed by passing a block to machine_input (in the input card
-
# set)
-
# - stores the output as a .txt file in the '+machine output' card;
-
# - can be changed by passing a filetype and/or a block to
-
# store_machine_output
-
#
-
#
-
# ## How does it work?
-
# Machine cards have a '+machine input' and a '+machine output' card. The
-
# '+machine input' card is a pointer to all input cards. Including the
-
# MachineInput module creates an 'on: save' event that runs the machines of
-
# all cards that are linked to that card via the +machine input pointer.
-
1
module MachineClassMethods
-
1
attr_accessor :output_config
-
-
1
def collect_input_cards &block
-
define_method :engine_input, &block
-
end
-
-
1
def prepare_machine_input &block
-
define_method :before_engine, &block
-
end
-
-
1
def machine_engine &block
-
define_method :engine, &block
-
end
-
-
1
def store_machine_output args={}, &block
-
5
output_config.merge!(args)
-
5
return unless block_given?
-
define_method :after_engine, &block
-
end
-
end
-
-
1
card_accessor :machine_output, type: FileID
-
1
card_accessor :machine_input, type: PointerID
-
-
1
def before_engine
-
end
-
-
1
def engine_input
-
2
ei = EngineInput.new self
-
2
ei.process
-
2
ei.new_input
-
end
-
-
# TODO: replace with call of extended_item_cards
-
# traverse through all levels of pointers and
-
# collect all item cards as input
-
1
class EngineInput
-
1
attr_accessor :new_input
-
-
1
def initialize machine_card
-
2
@machine_card = machine_card
-
2
@items = [machine_card]
-
2
@new_input = []
-
2
@extended = {}
-
2
@loop_limit = 5
-
end
-
-
1
def process
-
2
each_valid_item do
-
4
input_item = simple_item? ? @item : pointer_item
-
4
new_input << input_item if input_item
-
end
-
end
-
-
1
def simple_item?
-
4
@item.item_cards == [@item] # no pointer card
-
end
-
-
1
def pointer_item
-
2
@items.insert 0, @item.item_cards.reject(&:unknown?)
-
2
@items.flatten!
-
2
record_item
-
2
@item if @item != @machine_card && @item.known?
-
end
-
-
1
def record_item
-
2
@extended[@item] = @extended[@item].to_i + 1
-
end
-
-
1
def each_valid_item
-
2
until @items.empty?
-
4
@item = @items.shift
-
4
yield unless invalid_item?
-
end
-
end
-
-
1
def invalid_item?
-
4
@item.trash || @extended[@item.id].to_i > @loop_limit
-
end
-
end
-
-
1
def engine input
-
1
input
-
end
-
-
1
def after_engine output
-
1
filetype = output_config[:filetype]
-
1
file = Tempfile.new [id.to_s, ".#{filetype}"]
-
1
file.write output
-
1
file.rewind
-
1
Card::Auth.as_bot do
-
1
p = machine_output_card
-
1
p.file = file
-
1
p.save!
-
end
-
1
file.close
-
1
file.unlink
-
end
-
-
1
view :machine_output_url do
-
machine_output_url
-
end
-
-
1
class << self
-
1
def included host_class
-
6
host_class.extend(MachineClassMethods)
-
6
host_class.mattr_accessor :output_config
-
6
host_class.output_config = { filetype: "txt" }
-
-
6
define_machine_events host_class
-
end
-
-
1
def define_machine_events host_class
-
6
event_suffix = host_class.name.tr ":", "_"
-
6
event_name = "reset_machine_output_#{event_suffix}".to_sym
-
6
host_class.event event_name, after: :expire_related, changed: :content, on: :save do
-
reset_machine_output
-
end
-
end
-
end
-
-
1
include_set Abstract::Lock
-
-
1
def run_machine joint="\n"
-
1
before_engine
-
output =
-
1
input_item_cards.map do |input_card|
-
1
run_engine input_card
-
end.select(&:present?).join(joint)
-
1
after_engine output
-
end
-
-
1
def direct_machine_input? input_card
-
1
!input_card.collection? ||
-
input_card.respond_to?(:machine_input)
-
end
-
-
1
def run_engine input_card
-
1
return unless direct_machine_input? input_card
-
1
if (cached = fetch_cache_card(input_card)) && cached.content?
-
return cached.content
-
end
-
-
1
engine(input_from_card(input_card)).tap do |output|
-
1
cache_output_part input_card, output
-
end
-
end
-
-
1
def input_from_card input_card
-
1
if input_card.respond_to? :machine_input
-
1
input_card.machine_input
-
else
-
input_card.format._render_raw
-
end
-
end
-
-
1
def make_machine_output_coded mod=:machines
-
update_machine_output
-
Card::Auth.as_bot do
-
ENV["STORE_CODED_FILES"] = "true"
-
machine_output_card.update! storage_type: :coded, mod: mod,
-
codename: machine_output_codename
-
ENV["STORE_CODED_FILES"] = nil
-
end
-
end
-
-
1
def machine_output_codename
-
machine_output_card.name.parts.map do |part|
-
Card[part].codename&.to_s || Card[part].name.safe_key
-
end.join "_"
-
end
-
-
1
def input_item_cards
-
1
machine_input_card.item_cards
-
end
-
-
1
def machine_output_url
-
94
ensure_machine_output
-
94
machine_output_card.file.url # (:default, timestamp: false)
-
# to get rid of additional number in url
-
end
-
-
1
def machine_output_path
-
ensure_machine_output
-
machine_output_card.file.path
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Machine;
-
# Set: Abstract (Machine, OutputCache)
-
#
-
1
module OutputCache;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine/output_cache.rb"; end
-
1
def fetch_cache_card input_card, new=nil
-
2
new &&= { type_id: PlainTextID }
-
2
Card.fetch input_card.name, name, :machine_cache, new: new
-
end
-
-
1
def cache_output_part input_card, output
-
1
Auth.as_bot do
-
# save virtual cards first
-
# otherwise the cache card will save it to get the left_id
-
# and trigger the cache update again
-
1
input_card.save! if input_card.new_card?
-
-
1
cache_card = fetch_cache_card(input_card, true)
-
1
cache_card.update! content: output
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine/output_cache.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Machine;
-
# Set: Abstract (Machine, OutputUpdate)
-
#
-
1
module OutputUpdate;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine/output_update.rb"; end
-
1
def reset_machine_output
-
1
Auth.as_bot do
-
1
moc = machine_output_card
-
1
@updated_at = output_updated_at
-
1
moc.delete! if moc.real?
-
1
update_input_card
-
1
expire_if_source_file_changed @updated_at
-
end
-
end
-
-
1
def regenerate_machine_output
-
return unless ok?(:read)
-
lock { run_machine }
-
end
-
-
1
def update_machine_output
-
1
return unless ok?(:read)
-
1
lock do
-
1
update_input_card
-
1
expire_if_source_file_changed output_updated_at
-
1
run_machine
-
end
-
end
-
-
1
def ensure_machine_output
-
94
output = fetch :machine_output
-
94
return if output&.selected_content_action_id
-
update_machine_output
-
end
-
-
1
def update_input_card
-
2
if Card::Director.running_act?
-
input_card = attach_subcard! machine_input_card
-
input_card.content = ""
-
engine_input.each { |input| input_card << input }
-
else
-
2
machine_input_card.items = engine_input
-
end
-
end
-
-
1
def input_cards_with_changed_source output_updated
-
1
machine_input_card.extended_item_cards.select do |i_card|
-
1
i_card.try(:source_changed?, since: output_updated)
-
end
-
end
-
-
1
def expire_if_source_file_changed output_updated_at
-
2
return unless output_updated_at
-
1
changed = input_cards_with_changed_source(output_updated_at)
-
1
return if changed.empty?
-
1
changed.each(&:expire_machine_cache)
-
1
true
-
end
-
-
# regenerates the machine output if a source file of a input card has been changed
-
1
def update_if_source_file_changed
-
return unless expire_if_source_file_changed output_updated_at
-
regenerate_machine_output
-
end
-
-
1
def output_updated_at
-
2
return unless (output_card = machine_output_card)
-
2
if output_card.coded?
-
1
File.mtime output_card.file.path
-
else
-
1
output_card.updated_at
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine/output_update.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (MachineInput)
-
#
-
1
module MachineInput;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine_input.rb"; end
-
1
module MachineInputClassMethods
-
1
attr_accessor :machines_cql
-
-
1
def machine_input_for args
-
@machines_cql = args
-
end
-
-
1
def machine_input &block
-
7
define_method :machine_input, block
-
end
-
end
-
-
1
def self.included host_class
-
4
host_class.extend(MachineInputClassMethods)
-
4
host_class.machines_cql = {}
-
4
host_class.machine_input do
-
format._render_raw
-
end
-
4
event_suffix = host_class.name.tr ":", "_"
-
4
define_update_event event_suffix, host_class
-
4
define_delete_events event_suffix, host_class
-
end
-
-
1
def self.define_delete_events event_suffix, host_class
-
4
event_name = "before_machine_input_deleted_#{event_suffix}".to_sym
-
4
host_class.event event_name, :store, on: :delete do
-
# exclude self because it's on the way to the trash
-
# otherwise it will be created again with the reset_machine_output
-
# call in the event below
-
@involved_machines =
-
MachineInput.search_involved_machines(name, host_class)
-
.reject { |card| card == self }
-
end
-
4
event_name = "after_machine_input_deleted_#{event_suffix}".to_sym
-
4
host_class.event event_name, :finalize, on: :delete do
-
expire_machine_cache
-
@involved_machines.each do |item|
-
item.reset_machine_output if item.is_a? Machine
-
end
-
end
-
end
-
-
1
def self.define_update_event event_suffix, host_class
-
4
host_class.event(
-
"after_machine_input_updated_#{event_suffix}".to_sym, :integrate,
-
on: :save
-
) do
-
expire_machine_cache
-
MachineInput.search_involved_machines(name, host_class)
-
.each do |item|
-
item.reset_machine_output if item.is_a? Machine
-
end
-
end
-
end
-
-
1
def self.search_involved_machines name, host_class
-
cql_statement =
-
{ right_plus: [
-
{ codename: "machine_input" },
-
{ link_to: name }
-
] }.merge(host_class.machines_cql)
-
Card.search(cql_statement)
-
end
-
-
1
def expire_machine_cache
-
1
Card.search(right_plus: [{ codename: "machine_input" }, { link_to: name }],
-
return: :name).each do |machine_name|
-
1
cache_card = Card.fetch(name, machine_name, :machine_cache)
-
1
next unless cache_card&.content?
-
Auth.as_bot { cache_card.update! trash: true }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/machine_input.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Script)
-
#
-
# -*- encoding : utf-8 -*-
-
1
module Script;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/script.rb"; end
-
-
1
require "uglifier"
-
-
1
def self.included host_class
-
2
host_class.include_set Abstract::Machine
-
2
host_class.include_set Abstract::MachineInput
-
-
2
host_class.machine_input { standard_machine_input }
-
2
host_class.store_machine_output filetype: "js"
-
end
-
-
1
def standard_machine_input
-
js = format(:js)._render_core
-
js = compress_js js if compress_js?
-
comment_with_source js
-
end
-
-
1
def comment_with_source js
-
"//#{name}\n#{js}"
-
end
-
-
1
def compress_js input
-
Uglifier.compile input
-
rescue => e
-
# CoffeeScript is compiled in a view
-
# If there is a CoffeeScript syntax error we get the rescued view here
-
# and the error that the rescued view is no valid Javascript
-
# To get the original error we have to refer to Card::Error.current
-
raise Card::Error, compression_error_message(e)
-
end
-
-
1
def compression_error_message e
-
if Card::Error.current
-
Card::Error.current.message
-
else
-
"JavaScript::SyntaxError (#{name}): #{e.message}"
-
end
-
end
-
-
1
def compress_js?
-
Cardio.config.compress_javascript
-
end
-
-
1
def clean_html?
-
false
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def chunk_list # turn off autodetection of uri's
-
:nest_only
-
end
-
-
# def default_nest_view
-
# :raw
-
# end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:ace_editor
-
end
-
-
1
def ace_mode
-
:javascript
-
end
-
-
1
def content_changes action, diff_type, hide_diff=false
-
wrap_with(:pre) { super }
-
end
-
-
1
view :core do
-
script = card.format(:js).render_core
-
process_content highlight(script)
-
end
-
-
1
def highlight script
-
::CodeRay.scan(script, :js).div
-
end
-
end
-
-
1
def diff_args
-
{ diff_format: :text }
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/script.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (SkinBox)
-
#
-
1
module SkinBox;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/skin_box.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :box do
-
class_up "box-middle", "p-0"
-
voo.hide :customize_button, :box_middle
-
super()
-
end
-
-
1
view :box_bottom, template: :haml
-
-
1
view :customize_button, cache: :never do
-
customize_button
-
end
-
-
1
def customize_button target: parent&.card, text: "Apply and customize"
-
return "" unless card.codename.present?
-
theme = card.codename.match(/^(?<theme_name>.+)_skin$/).capture(:theme_name)
-
link_to_card target, text,
-
path: { action: :update, card: { content: "[[#{card.name}]]" },
-
customize: true, theme: theme },
-
class: "btn btn-sm btn-outline-primary mr-2"
-
end
-
-
1
view :box_middle do
-
return unless card.field(:image)
-
field_nest(:image, view: :full_width, size: :large)
-
end
-
-
1
def select_button target=parent.card
-
link_to_card target, "Apply",
-
path: { action: :update, card: { content: "[[#{card.name}]]" } },
-
class: "btn btn-sm btn-primary"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/abstract/skin_box.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (ResetMachines)
-
#
-
1
module ResetMachines;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/all/reset_machines.rb"; end
-
1
module ClassMethods
-
1
def reset_script_machine
-
Auth.as_bot do
-
card = Card[:all, :script, :machine_output]
-
if card
-
card.update_columns trash: true
-
card.expire
-
Card::Virtual.where(right_id: MachineCacheID).delete_all
-
end
-
end
-
end
-
-
1
def reset_all_machines
-
Auth.as_bot do
-
Card.search(right: { codename: "machine_output" }).each do |card|
-
card.update_columns trash: true
-
card.expire
-
end
-
Card::Virtual.where(right_id: MachineCacheID).delete_all
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/all/reset_machines.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+MachineCache" cards
-
#
-
1
module MachineCache;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/right/machine_cache.rb"; end
-
1
include_set Abstract::VirtualCache
-
-
1
def clean_html?
-
false
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/right/machine_cache.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+MachineInput" cards
-
#
-
1
module MachineInput;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/right/machine_input.rb"; end
-
1
def followable?
-
1
false
-
end
-
-
1
def history?
-
5
false
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/right/machine_input.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+MachineOutput" cards
-
#
-
1
module MachineOutput;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/right/machine_output.rb"; end
-
1
def followable?
-
1
false
-
end
-
-
1
def ok_to_read
-
2
left.ok_to_read
-
end
-
-
1
def history?
-
5
false
-
end
-
-
1
event :remove_codename, :prepare_to_validate,
-
on: :delete,
-
1
when: proc { |c| c.codename.present? } do
-
# load file before deleting codename otherwise it will fail later
-
1
attachment
-
1
self.codename = nil
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :not_found do
-
1
if update_machine_output_live?
-
1
Card::Cache.reset_all # FIXME: wow, this is overkill, no?
-
1
root.error_status = 302
-
1
card.left.update_machine_output
-
1
card_path card.left.machine_output_url
-
else
-
super()
-
end
-
end
-
-
1
def update_machine_output_live?
-
case
-
1
when !card.left.is_a?(Abstract::Machine) then false # must be a machine
-
when card.left.locked? then false # machine must not be running
-
1
when card.new_card? then true # always update if new
-
else
-
# must want current output (won't re-output old stuff)
-
(selected_id = card.selected_action_id) &&
-
selected_id == card.last_action_id
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/right/machine_output.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptDecko"
-
#
-
1
module ScriptDecko;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_decko.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
def source_files
-
%w[mod editor name_editor autosave doubleclick layout navbox upload
-
slot modal overlay recaptcha slotter bridge
-
nest_editor nest_editor_rules nest_editor_options nest_editor_name
-
link_editor
-
components decko follow card_menu slot_ready
-
filter filter_links filter_items selectable_filtered_content].map do |n|
-
"decko/#{n}.js.coffee"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_decko.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptHtml5shivPrintshiv"
-
#
-
1
module ScriptHtml5shivPrintshiv;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_html5shiv_printshiv.rb"; end
-
1
include_set Abstract::CodeFile
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :script_tag, perms: :none do
-
23
<<-HTML.strip_heredoc
-
<!--[if lt IE 9]>
-
#{javascript_include_tag card.machine_output_url}
-
<![endif]-->
-
HTML
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_html5shiv_printshiv.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptJquery"
-
#
-
1
module ScriptJquery;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_jquery.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
def source_files
-
["vendor/jquery_rails/vendor/assets/javascripts/jquery3.js",
-
"vendor/jquery_rails/vendor/assets/javascripts/jquery_ujs.js"]
-
end
-
-
1
def source_dir
-
""
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_jquery.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptJqueryHelper"
-
#
-
1
module ScriptJqueryHelper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_jquery_helper.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::ScriptLibraries.add_item :script_jquery_helper
-
-
1
def source_files
-
# jquery-ui includes all interaction components, the dialog and the autocomplete widget
-
# and all dependencies for those
-
# decko depends on autocomplete, sortable, jquery.autosize and jquery.fileupload
-
# the dialog widget is not used in decko but in wikirate
-
# don't know if iframe-transport is needed but it used to be there
-
%w[jquery-ui.js
-
jquery.autosize.js
-
../../vendor/jquery_file_upload/js/jquery.fileupload.js
-
../../vendor/jquery_file_upload/js/jquery.iframe-transport.js]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/script_jquery_helper.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleBootstrapCompatible"
-
#
-
1
module StyleBootstrapCompatible;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/style_bootstrap_compatible.rb"; end
-
1
include_set Abstract::CodeFile
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/style_bootstrap_compatible.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleCards"
-
#
-
1
module StyleCards;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/style_cards.rb"; end
-
1
include_set Abstract::CodeFile
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/style_cards.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleJqueryUiSmoothness"
-
#
-
1
module StyleJqueryUiSmoothness;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/style_jquery_ui_smoothness.rb"; end
-
1
include_set Abstract::CodeFile
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/self/style_jquery_ui_smoothness.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "CoffeeScript" cards
-
#
-
# -*- encoding : utf-8 -*-
-
1
module CoffeeScript;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/coffee_script.rb"; end
-
-
1
require "coffee-script"
-
-
1
include_set Abstract::Script
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def ace_mode
-
:coffee
-
end
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
compile_coffee _render_raw
-
end
-
-
1
def compile_coffee script
-
::CoffeeScript.compile script
-
rescue => e
-
line_nr = e.to_s.match(/\[stdin\]:(\d*)/)&.capture(0)&.to_i
-
line = script.lines[line_nr - 1] if line_nr
-
raise Card::Error, "CoffeeScript::Error (#{card.name}): #{e.message}: #{line}"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/coffee_script.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Css" cards
-
#
-
# -*- encoding : utf-8 -*-
-
1
module Css;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/css.rb"; end
-
-
1
require "sassc"
-
1
require "benchmark"
-
-
1
include_set Abstract::Machine
-
1
include_set Abstract::MachineInput
-
-
1
store_machine_output filetype: "css"
-
-
1
machine_input do
-
1
compress_css format(format: :css)._render_core
-
end
-
-
1
def compress_css input
-
1
compress_css? ? SassC::Engine.new(input, style: :compressed).render : input
-
rescue => e
-
raise Card::Error, css_compression_error(e)
-
end
-
-
1
def css_compression_error error
-
# scss is compiled in a view
-
# If there is a scss syntax error we get the rescued view here
-
# and the error that the rescued view is no valid css
-
# To get the original error we have to refer to Card::Error.current
-
if Card::Error.current
-
Card::Error.current.message
-
else
-
"Sass::SyntaxError (#{name}): #{error.message}"
-
end
-
end
-
-
1
def clean_html?
-
false
-
end
-
-
1
def compress_css?
-
1
return true
-
!Rails.env.development?
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
# def default_nest_view
-
# :raw
-
# end
-
-
1
def chunk_list # turn off autodetection of uri's
-
1
:references
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:ace_editor
-
end
-
-
1
def ace_mode
-
:css
-
end
-
-
1
def default_nest_view
-
:closed
-
end
-
-
1
view :core do
-
# FIXME: scan must happen before process for inclusion interactions to
-
# work, but this will likely cause
-
# problems with including other css?
-
process_content ::CodeRay.scan(_render_raw, :css).div, size: :icon
-
end
-
-
1
def content_changes action, diff_type, hide_diff=false
-
wrap_with(:pre) { super }
-
end
-
end
-
-
2
module CssFormat; module_parent.send :register_set_format, Card::Format::CssFormat, self; extend Card::Set::AbstractFormat
-
1
view :import do
-
%{\n@import url("#{_render_url}");\n}
-
end
-
end
-
-
1
def diff_args
-
{ diff_format: :text }
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/css.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "JavaScript" cards
-
#
-
# -*- encoding : utf-8 -*-
-
1
module JavaScript;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/java_script.rb"; end
-
-
1
include_set Abstract::Script
-
-
2
module JsFormat; module_parent.send :register_set_format, Card::Format::JsFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
_render_raw
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/java_script.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Scss" cards
-
#
-
1
module Scss;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/scss.rb"; end
-
1
include_set Type::Css
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :core, cache: :never do
-
1
compile_scss(process_content(_render_raw))
-
end
-
-
1
def compile_scss scss, style=:expanded
-
1
SassC::Engine.new(scss, style: style).render
-
rescue SassC::SyntaxError => e
-
raise Card::Error,
-
"SassC::SyntaxError (#{card.name}:#{e.sass_backtrace}): #{e.message}"
-
# "#{#scss.lines[e.sass_line - 1]}\n" \
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def ace_mode
-
:scss
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/scss.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Skin" cards
-
#
-
1
module Skin;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/skin.rb"; end
-
1
include_set Abstract::MachineInput
-
1
include_set Abstract::SkinBox
-
1
include_set Pointer
-
-
1
def machine_input
-
# only the item of a skin card contribute input to the machine
-
# not the skin card itself
-
""
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-machines/set/type/skin.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Permission)
-
#
-
1
module Permission;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/abstract/permission.rb"; end
-
-
1
def standardize_items
-
4
super unless content == "_left"
-
end
-
-
1
def options_rule_card
-
1301
Card[:cards_with_account]
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :pointer_core do
-
wrap_with :div, pointer_items, class: "pointer-list"
-
end
-
-
1
view :core, cache: :never do
-
if card.content == "_left"
-
core_inherit_content
-
else
-
render! :pointer_core
-
end
-
end
-
-
1
view :one_line_content, cache: :never do
-
render_core items: { view: :link }
-
end
-
-
1
view :input do
-
item_names = inheriting? ? [] : card.item_names
-
%(
-
#{_render_hidden_content_field}
-
<div class="perm-editor">
-
#{inheritance_checkbox}
-
<div class="perm-group perm-vals perm-section">
-
<h5 class="text-muted">Groups</h5>
-
#{groups item_names}
-
</div>
-
-
<div class="perm-indiv perm-vals perm-section">
-
<h5 class="text-muted">Individuals</h5>
-
#{list_input item_list: item_names, extra_css_class: 'perm-indiv-ul'}
-
</div>
-
</div>
-
)
-
end
-
-
1
private
-
-
1
def groups item_names
-
group_options.map do |option|
-
checked = !item_names.delete(option.name).nil?
-
icon = icon_tag "open_in_new", "link-muted"
-
option_link = link_to_card option.name, icon, target: "decko_role"
-
box = check_box_tag "#{option.key}-perm-checkbox",
-
option.name, checked, class: "perm-checkbox-button"
-
<<-HTML
-
<div class="form-check checkbox">
-
<label class="form-check-label">
-
#{box} #{option.name} #{option_link}
-
</label>
-
</div>
-
HTML
-
end * "\n"
-
end
-
-
1
def group_options
-
Auth.as_bot do
-
Card.search({ type_id: RoleID, sort: "name" }, "roles by name")
-
end
-
end
-
-
1
def inheritable?
-
@inheritable ||=
-
begin
-
set_name = card.name.trunk_name
-
set_card = Card.fetch(set_name)
-
not_set = set_card && set_card.type_id != SetID
-
not_set ? false : set_card.inheritable?
-
end
-
end
-
-
1
def inheriting?
-
@inheriting ||= inheritable? && card.content == "_left"
-
end
-
-
1
def inheritance_checkbox
-
return unless inheritable?
-
<<-HTML
-
<div class="perm-inheritance perm-section">
-
#{check_box_tag 'inherit', 'inherit', inheriting?}
-
<label>
-
#{core_inherit_content}
-
#{wrap_with(:a, title: "use left's #{card.name.tag} rule") { '?' }}
-
</label>
-
</div>
-
HTML
-
end
-
-
1
def core_inherit_content
-
text = if in_context_of_self_set?
-
core_inherit_for_content_for_self_set
-
else
-
"Inherit from left card"
-
end
-
%(<span class="inherit-perm">#{text}</span>)
-
end
-
-
1
def in_context_of_self_set?
-
return false unless @set_context
-
@set_context.to_name.tag_name.key == Card[:self].key
-
end
-
-
1
def core_inherit_for_content_for_self_set
-
task = card.tag.codename
-
ancestor = Card[@set_context.trunk_name.trunk_name]
-
links = ancestor.who_can(task).map do |card_id|
-
link_to_card card_id, nil, target: args[:target]
-
end * ", "
-
"Inherit ( #{links} )"
-
rescue
-
"Inherit"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/abstract/permission.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (TemplatedNests)
-
#
-
1
module TemplatedNests;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/abstract/templated_nests.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
with_nest_mode :template do
-
super()
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/abstract/templated_nests.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (SupportsContentOptions)
-
#
-
1
module SupportsContentOptions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/all/supports_content_options.rb"; end
-
1
def supports_content_options?
-
false
-
end
-
-
1
def supports_content_option_view?
-
false
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/all/supports_content_options.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Autoname" cards
-
#
-
1
module Autoname;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/autoname.rb"; end
-
1
def history?
-
2
false
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/autoname.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Comment" cards
-
#
-
1
module Comment;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/comment.rb"; end
-
1
include_set Abstract::Permission
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/comment.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+ContentOptionView" cards
-
#
-
1
module ContentOptionView;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/content_option_view.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def quick_edit
-
if card.left.prototype_default_card&.try(:show_content_options?) &&
-
card.left.prototype.rule_card(:input_type)&.supports_content_option_view?
-
super
-
else
-
""
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/content_option_view.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+ContentOptions" cards
-
#
-
1
module ContentOptions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/content_options.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def quick_edit
-
card.left.prototype_default_card.try(:show_content_options?) ? super : ""
-
end
-
-
1
def quick_editor
-
wrap_type_formgroup do
-
type_field class: "type-field rule-type-field _submit-on-select"
-
end +
-
wrap_content_formgroup do
-
text_field :content, class: "d0-card-content _submit-after-typing"
-
end
-
end
-
-
1
def visible_cardtype_groups
-
{ "Organize" => %w[List Pointer] }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/content_options.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Create" cards
-
#
-
1
module Create;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/create.rb"; end
-
1
include_set Abstract::Permission
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/create.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Default" cards
-
#
-
1
module Default;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/default.rb"; end
-
1
include_set Abstract::TemplatedNests
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :one_line_content do
-
raw = _render_raw
-
"#{card.type_name} : #{raw.present? ? raw : '<em>empty</em>'}"
-
end
-
-
1
def quick_form_opts
-
super.merge "data-update-foreign-slot":
-
".card-slot.quick_edit-view.RIGHT-Xinput_type,"\
-
".card-slot.quick_edit-view.RIGHT-Xcontent_option"\
-
".card-slot.quick_edit-view.RIGHT-Xcontent_option_view"
-
end
-
-
1
def quick_editor
-
wrap_type_formgroup do
-
type_field class: "type-field rule-type-field _submit-on-select"
-
end +
-
wrap_content_formgroup do
-
text_field :content, class: "d0-card-content _submit-after-typing"
-
end
-
end
-
-
1
def visible_cardtype_groups
-
hash = ::Card::Set::Self::Cardtype::GROUP.slice("Text", "Data", "Upload")
-
hash["Organize"] = ["List", "Pointer", "Link list", "Nest list"]
-
hash
-
end
-
end
-
-
1
def empty_ok?
-
true
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/default.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Delete" cards
-
#
-
1
module Delete;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/delete.rb"; end
-
1
include_set Abstract::Permission
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/delete.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Guide" cards
-
#
-
# include_set Abstract::TemplatedNests
-
1
module Guide;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/guide.rb"; end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def raw_help_text
-
# LOCALIZE
-
"Appears in the full editor view to guide users."
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/guide.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Help" cards
-
#
-
1
module Help;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/help.rb"; end
-
1
include_set Abstract::TemplatedNests
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :popover do
-
popover_link _render_core
-
end
-
-
1
def quick_editor
-
# TODO: refactor when voo.input_type is ready. (and use class_up)
-
formgroup "Content", input: :content, help: false do
-
text_field :content, value: card.content,
-
class: "d0-card-content _submit-after-typing"
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/help.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+InputType" cards
-
#
-
1
module InputType;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/input_type.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def quick_editor
-
@submit_on_change = true
-
super
-
end
-
-
1
def quick_form_opts
-
super.merge "data-update-foreign-slot":
-
".card-slot.quick_edit-view.RIGHT-Xcontent_option_view"
-
end
-
-
1
def default_input_type
-
:radio
-
end
-
-
1
def raw_help_text
-
"edit interface for list cards"
-
end
-
-
# def option_label_text option_name
-
# super.downcase
-
# end
-
-
1
def quick_edit
-
card.left.prototype_default_card.try(:show_input_type?) ? super : ""
-
end
-
end
-
-
1
def option_names
-
left.prototype_default_card&.try(:input_type_content_options) || super
-
end
-
-
1
def supports_content_option_view?
-
item_name.in? ["checkbox", "radio", "filtered list"]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/input_type.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Read" cards
-
#
-
1
module Read;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/read.rb"; end
-
1
include Abstract::Permission
-
-
2
format :html do include Abstract::Permission::HtmlFormat end
-
-
1
event :cascade_read_rule, :finalize, after: :update_rule_cache, when: :is_rule? do
-
2
return unless name_is_changing? || trash_is_changing?
-
-
2
update_read_ruled_cards
-
end
-
-
1
def update_read_ruled_cards
-
2
Card::Rule.clear_read_rule_cache
-
2
Card.cache.reset # maybe be more surgical, just Auth.user related
-
2
expire # probably shouldn't be necessary,
-
# but was sometimes getting cached version when card should be in the
-
# trash. could be related to other bugs?
-
-
2
processed = update_read_rules_of_set_members
-
2
update_cards_with_read_rule_id processed unless new?
-
end
-
-
1
def update_read_rules_of_set_members
-
2
return unless rule_pattern_index
-
-
2
each_member do |member, processed|
-
2
processed << member.key
-
2
member.update_read_rule unless member_has_overriding_rule?(member)
-
end
-
end
-
-
1
def member_has_overriding_rule? member
-
2
pattern_index(Card.fetch_id(member.read_rule_class)) < rule_pattern_index
-
end
-
-
# cards with this card as a read_rule_id
-
# These may include cards that are no longer set members if the card was renamed
-
# (edge case)
-
1
def update_cards_with_read_rule_id processed
-
2
processed ||= ::Set.new
-
2
Card::Auth.as_bot do
-
2
Card.search(read_rule_id: id) do |card|
-
6
card.update_read_rule unless processed.include?(card.key)
-
end
-
end
-
end
-
-
1
def each_member
-
2
Auth.as_bot do
-
2
all_members.each_with_object(::Set.new) do |member, processed|
-
2
yield member, processed
-
end
-
end
-
end
-
-
1
def all_members
-
2
rule_set.item_cards limit: 0
-
end
-
-
1
def rule_pattern_index
-
4
return if trash
-
-
4
@rule_pattern_index ||= pattern_index rule_set&.tag&.id
-
end
-
-
1
def pattern_index pattern_id
-
4
pattern_ids.index(pattern_id) || invalid_pattern_id(pattern_id)
-
end
-
-
1
def pattern_ids
-
4
@pattern_ids ||= set_patterns.map(&:pattern_id)
-
end
-
-
1
def invalid_pattern_id pattern_id
-
Rails.logger.info "invalid pattern id for read rule: #{pattern_id}"
-
end
-
-
1
event :process_read_rule_update_queue, :finalize do
-
11
left&.update_read_rule
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/read.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Script" cards
-
#
-
1
module Script;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/script.rb"; end
-
1
include_set Abstract::Machine
-
-
1
store_machine_output filetype: "js"
-
-
1
def ok_to_read
-
1
true
-
end
-
-
1
view :javascript_include_tag do
-
%(
-
<script src="#{card.machine_output_url}" type="text/javascript"></script>
-
)
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def raw_help_text
-
"JavaScript (or CoffeeScript) for card's page."
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/script.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Structure" cards
-
#
-
1
module Structure;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/structure.rb"; end
-
1
include_set Abstract::TemplatedNests
-
-
2
module RssFormat; module_parent.send :register_set_format, Card::Format::RssFormat, self; extend Card::Set::AbstractFormat
-
1
def raw_feed_items
-
[card]
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :one_line_content do
-
"#{_render_type} : #{_render_raw}"
-
end
-
-
1
def visible_cardtype_groups
-
hash = ::Card::Set::Self::Cardtype::GROUP.slice("Text")
-
hash["Organize"] = ["Search", "Nest list"]
-
hash
-
end
-
end
-
-
1
event :update_structurees_references, :integrate,
-
when: :update_structurees_references? do
-
return unless (query = structuree_query)
-
-
Auth.as_bot do
-
query.run.each(&:update_references_out)
-
end
-
end
-
-
1
def update_structurees_references?
-
db_content_changed? || action == :delete
-
end
-
-
1
event :reset_cache_to_use_new_structure,
-
before: :update_structurees_references do
-
Card::Cache.reset_hard
-
Card::Cache.reset_soft
-
end
-
-
1
event :update_structurees_type, :finalize,
-
changed: :type_id, when: proc { |c| c.assigns_type? } do
-
update_structurees type_id: type_id
-
end
-
-
1
def structuree_names
-
return [] unless (query = structuree_query(return: :name))
-
-
Auth.as_bot do
-
query.run
-
end
-
end
-
-
1
def update_structurees args
-
# note that this is not smart about overriding templating rules
-
# for example, if someone were to change the type of a
-
# +*right+*structure rule that was overridden
-
# by a +*type plus right+*structure rule, the override would not be respected.
-
return unless (query = structuree_query(return: :id))
-
-
Auth.as_bot do
-
query.run.each_slice(100) do |id_batch|
-
Card.where(id: id_batch).update_all args
-
end
-
end
-
end
-
-
1
def structuree_query args={}
-
set_card = trunk
-
return unless set_card.type_id == SetID
-
-
set_card.fetch_query args
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/structure.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Style" cards
-
#
-
1
module Style;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/style.rb"; end
-
1
require "sassc"
-
1
include_set Abstract::Machine
-
-
1
store_machine_output filetype: "css"
-
-
1
def ok_to_read
-
25
true
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
# turn off autodetection of uri's
-
1
def chunk_list
-
:nest_only
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
HIDDEN_SKINS = %w[bootstrap_default_skin themeless_bootstrap_skin bootstrap_default_skin
-
classic_bootstrap_skin].freeze
-
-
1
def default_item_view
-
:bar
-
end
-
-
1
view :input, template: :haml
-
-
1
def themes
-
card.rule_card(:content_options).item_cards
-
end
-
-
1
def selectable_themes
-
themes.reject do |theme_card|
-
theme_card.right&.codename == :stylesheets ||
-
theme_card.key.in?(HIDDEN_SKINS)
-
end
-
end
-
end
-
-
1
event :customize_theme, :prepare_to_validate, on: :update, when: :customize_theme? do
-
skin_name = free_skin_name
-
add_subcard skin_name, type_id: CustomizedBootswatchSkinID
-
self.content = "[[#{skin_name}]]"
-
end
-
-
1
def free_skin_name
-
name = "#{@theme} skin customized"
-
if Card.exist?(name)
-
name = "#{name} 1"
-
name.next! while Card.exist?(name)
-
end
-
name
-
end
-
-
1
def customize_theme?
-
Env.params[:customize].present? && (@theme = Env.params[:theme]).present?
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/style.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Update" cards
-
#
-
1
module Update;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/update.rb"; end
-
1
include_set Abstract::Permission
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/right/update.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Autoname"
-
#
-
1
module Autoname;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/autoname.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :templating, position: 4,
-
help_text: "Autogenerate name for new cards by incrementing this value. "\
-
"[[http://decko.org/autonaming|more]]"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/autoname.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Captcha"
-
#
-
1
module Captcha;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/captcha.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :permission, position: 5,
-
help_text: "Anti-spam setting. Requires non-signed-in users to complete a "\
-
"[[http://decko.org/captcha|captcha]] before adding or editing "\
-
"cards (where permitted)."
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/captcha.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ContentOptionView"
-
#
-
1
module ContentOptionView;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/content_option_view.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :editing, position: 6,
-
restricted_to_type: %i[list pointer session],
-
rule_type_editable: false,
-
help_text: "Label view for radio button and checkbox items. "\
-
"[[http://decko.org/Pointer|more]]",
-
applies: lambda { |prototype|
-
prototype.supports_content_options? &&
-
prototype.rule_card(:input_type)&.supports_content_option_view?
-
}
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/content_option_view.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ContentOptions"
-
#
-
1
module ContentOptions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/content_options.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :editing, position: 5,
-
restricted_to_type: %i[list pointer session],
-
rule_type_editable: true,
-
help_text: "Value options for [[List]] and [[Pointer]] and cards. "\
-
"Can itself be a List or a [[Search]]. "\
-
"[[http://decko.org/Pointer|more]]",
-
applies: lambda { |prototype|
-
prototype.rule_card(:input_type).supports_content_options?
-
}
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/content_options.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Create"
-
#
-
1
module Create;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/create.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :permission, position: 1, rule_type_editable: false,
-
short_help_text: "who can create cards",
-
help_text: "Who can create new cards"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/create.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "CsvStructure"
-
#
-
1
module CsvStructure;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/csv_structure.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :templating, position: 3, rule_type_editable: true
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/csv_structure.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Default"
-
#
-
1
module Default;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/default.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :templating, position: 2, rule_type_editable: true,
-
short_help_text: "type/content template for new cards"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/default.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "DefaultHtmlView"
-
#
-
1
module DefaultHtmlView;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/default_html_view.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :other, position: 4, rule_type_editable: false
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/default_html_view.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Delete"
-
#
-
1
module Delete;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/delete.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :permission, position: 4, rule_type_editable: false,
-
short_help_text: "who can delete cards",
-
help_text: "Who can delete cards"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/delete.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "FollowFields"
-
#
-
1
module FollowFields;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/follow_fields.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :other, position: 5, rule_type_editable: false
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/follow_fields.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Guide"
-
#
-
1
module Guide;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/guide.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :editing, position: 3, rule_type_editable: true,
-
short_help_text: "appears in the full editor view to guide users"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/guide.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Head"
-
#
-
1
module Head;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/head.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :webpage, position: 1, rule_type_editable: false,
-
short_help_text: "head tag content",
-
help_text: "head tag content"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/head.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Help"
-
#
-
1
module Help;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/help.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :editing, position: 1, rule_type_editable: true,
-
short_help_text: "help text people will see when editing",
-
help_text: "[[http://decko.org/custom_help_text|Help text]] "\
-
"people will see when editing."
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/help.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "InputType"
-
#
-
1
module InputType;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/input_type.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :editing,
-
position: 3,
-
rule_type_editable: false,
-
short_help_text: "edit interface"
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def raw_help_text
-
"Configure [[https://ace.c9.io/|ace]], "\
-
"Decko's default code editor, using these available "\
-
"[[https://github.com/ajaxorg/ace/wiki/Configuring-Ace|options]]."
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/input_type.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Layout"
-
#
-
1
module Layout;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/layout.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :webpage, position: 3, rule_type_editable: false,
-
help_text: "HTML structure of card's page "\
-
"[[http://decko.org/layouts | more]]"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/layout.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "OnCreate"
-
#
-
1
module OnCreate;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/on_create.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :event, position: 1, rule_type_editable: false,
-
help_text: "Configure events to be executed when card is created"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/on_create.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "OnDelete"
-
#
-
1
module OnDelete;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/on_delete.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :event, position: 3, rule_type_editable: false,
-
help_text: "Configure events to be executed when card is deleted"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/on_delete.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "OnUpdate"
-
#
-
1
module OnUpdate;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/on_update.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :event, position: 2, rule_type_editable: false,
-
help_text: "Configure events to be executed when card is updated"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/on_update.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Read"
-
#
-
1
module Read;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/read.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :permission, position: 2, rule_type_editable: false,
-
short_help_text: "who can view cards",
-
help_text: "Who can view cards in the [[set]]."
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/read.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "RecentSettings"
-
#
-
1
module RecentSettings;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/recent_settings.rb"; end
-
1
def history?
-
30
false
-
end
-
-
1
def followable?
-
false
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/recent_settings.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Script"
-
#
-
1
module Script;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/script.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :webpage, position: 5
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/script.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Structure"
-
#
-
1
module Structure;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/structure.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :templating, position: 2, rule_type_editable: true,
-
short_help_text: "control card's content / structure",
-
help_text: "Controls cards' content / structure. "\
-
"[[http://decko.org/formatting|more]]"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/structure.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Style"
-
#
-
1
module Style;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/style.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :webpage, position: 4,
-
help_text: "Skin (collection of stylesheets) for card's page. "\
-
"[[http://decko.org/skins|more]]"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/style.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "TableOfContents"
-
#
-
1
module TableOfContents;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/table_of_contents.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :other, position: 1, rule_type_editable: false,
-
help_text: "Autogenerate [[http://decko.org/table_of_contents|"\
-
"table of contents]] on cards with at least this many headers "\
-
'("0" means never).'
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/table_of_contents.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Thanks"
-
#
-
1
module Thanks;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/thanks.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :other, position: 3, rule_type_editable: false,
-
short_help_text: "destination after card is created",
-
help_text: "Destination after card is created. "\
-
"[[http://decko.org/Custom_thank_you_messages_for_forms|more]]"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/thanks.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Update"
-
#
-
1
module Update;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/update.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :permission, position: 3, rule_type_editable: false,
-
short_help_text: "who can update cards",
-
help_text: "Who can update cards"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/self/update.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Setting" cards
-
#
-
# require "json"
-
1
module Setting;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/settings/set/type/setting.rb"; end
-
-
1
def self.member_names
-
@@member_names ||= begin
-
Card.search(
-
{ type_id: SettingID, return: "key" },
-
"all setting cards"
-
).each_with_object({}) do |card_key, hash|
-
hash[card_key] = true
-
end
-
end
-
end
-
-
2
module DataFormat; module_parent.send :register_set_format, Card::Format::DataFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
cql = { left: { type: SetID },
-
right: card.id,
-
limit: 0 }
-
Card.search(cql).compact.map { |c| nest c }
-
end
-
end
-
-
1
def count
-
Card.search left: { type: SetID }, right: id, limit: 0, return: :count
-
end
-
-
1
def set_classes_with_rules
-
Card.set_patterns.reverse.map do |set_class|
-
cql = { left: { type: SetID },
-
right: id,
-
sort: %w[content name],
-
limit: 0 }
-
cql[:left][(set_class.anchorless? ? :id : :right_id)] = set_class.pattern_id
-
-
rules = Card.search cql
-
[set_class, rules] unless rules.empty?
-
end.compact
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def rule_link rule, text
-
link_to_card rule, text, path: { view: :modal_rule },
-
slotter: true, "data-modal-class": "modal-lg"
-
end
-
-
1
view :core do
-
haml do
-
<<-'HAML'.strip_heredoc
-
= _render_rule_help
-
%h3 All #{card.name.tr "*", ""} rules that apply to
-
- card.set_classes_with_rules.each do |klass, rules|
-
%p
-
%h5
-
= klass.generic_label.downcase
-
- if klass.anchorless?
-
= nest rules.first, view: :bar, show: :full_name
-
- else
-
- rules.each do |rule|
-
= nest rule, view: :bar
-
HAML
-
end
-
end
-
-
# Because +*help content renders in "template" mode when you render its content
-
# directly, we render the help text in the context of the *all+<setting> card
-
1
view :rule_help do
-
nest [:all, card.name], view: :rule_help
-
end
-
-
1
view :one_line_content do
-
render_rule_help
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
def items_for_export
-
Card.search left: { type: SetID }, right: card.id, limit: 0
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/settings/set/type/setting.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (FilterHelper)
-
#
-
# TODO: move sort/filter handling out of card and into base format
-
1
module FilterHelper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/00_filter_helper.rb"; end
-
# sorting and filtering is about viewing the data, not altering the data itself.
-
-
1
def sort_hash
-
75
sort_param.present? ? { sort: sort_param } : {}
-
end
-
-
1
def filter_param field
-
filter_hash[field.to_sym]
-
end
-
-
# FIXME: it is inconsistent that #sort_hash has :sort as the key, but
-
# #filter_hash is the _value_ of the hash with :filter as the key.
-
1
def filter_hash
-
75
@filter_hash ||=
-
75
Env.params[:filter].present? ? Env.hash(Env.params[:filter]) : default_filter_hash
-
end
-
-
1
def sort_param
-
75
@sort_param ||= safe_sql_param :sort
-
end
-
-
1
def safe_sql_param key
-
75
param = Env.params[key]
-
75
param.blank? ? nil : Card::Query.safe_sql(param)
-
end
-
-
1
def filter_keys_with_values
-
filter_keys.map do |key|
-
values = filter_param(key)
-
values.present? ? [key, values] : next
-
end.compact
-
end
-
-
# initial values for filtered search
-
1
def default_filter_hash
-
75
{}
-
end
-
-
1
def offset
-
param_to_i :offset, 0
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
delegate :filter_hash, :sort_hash, :filter_param, :sort_param,
-
:all_filter_keys, to: :card
-
-
1
def extra_paging_path_args
-
super.merge filter_and_sort_hash
-
end
-
-
1
def filter_and_sort_hash
-
sort_hash.merge filter: filter_hash
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/00_filter_helper.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (SearchParams)
-
#
-
1
module SearchParams;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/02_search_params.rb"; end
-
1
include_set Abstract::PagingParams
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def offset
-
search_params[:offset] || 0
-
end
-
-
1
def search_params
-
2
@search_params ||= default_search_params
-
end
-
-
# used for override
-
1
def default_search_params
-
1
if (qparams = query_params)
-
paging_params.merge vars: qparams
-
else
-
1
paging_params
-
end
-
end
-
-
1
def paging_params
-
1
{ limit: limit_param, offset: offset_param }
-
end
-
-
1
def query_params
-
1
return nil unless (vars = params[:query])
-
-
Env.hash vars
-
end
-
-
1
def default_limit
-
100
-
end
-
-
1
def extra_paging_path_args
-
return {} unless (vars = query_params)
-
-
{ query: vars }
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def default_limit
-
1
Cardio.config.paging_limit || 20
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
def default_limit
-
20
-
end
-
end
-
-
2
module RssFormat; module_parent.send :register_set_format, Card::Format::RssFormat, self; extend Card::Set::AbstractFormat
-
1
def default_limit
-
25
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/02_search_params.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Filter)
-
#
-
1
module Filter;
-
1
extend Card::Set
-
3
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter.rb"; end
-
1
include_set Abstract::Utility
-
-
1
def filter_class
-
Card::FilterQuery
-
end
-
-
1
def filter_keys
-
[:name]
-
end
-
-
1
def filter_keys_from_params
-
filter_hash.keys.map(&:to_sym) - [:not_ids]
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def sort_options
-
{ "Alphabetical": :name, "Recently Added": :create }
-
end
-
-
1
view :filtered_content, template: :haml, wrap: :slot
-
-
1
view :selectable_filtered_content, template: :haml, cache: :never
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Filter;
-
# Set: Abstract (Filter, FilterForm)
-
#
-
1
module FilterForm;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter/filter_form.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# sort and filter ui
-
1
view :filter_form, cache: :never do
-
filter_fields slot_selector: "._filter-result-slot",
-
sort_field: _render(:sort_formgroup)
-
end
-
-
1
view :quick_filters, cache: :never do
-
return "" unless quick_filter_list.present?
-
-
haml :quick_filters, filter_list: normalized_quick_filter_list
-
end
-
-
1
def normalized_quick_filter_list
-
quick_filter_list.map do |hash|
-
hash = hash.clone
-
filter_key = hash.keys.first
-
{
-
text: (hash.delete(:text) || hash[filter_key]),
-
icon: (hash.delete(:icon) || mapped_icon_tag(filter_key)),
-
# FIXME: mapped_icon_tag is a wikirate concept
-
class: css_classes(hash.delete(:class),
-
"_filter-link quick-filter-by-#{filter_key}"),
-
filter: JSON(hash[:filter] || hash)
-
}
-
end
-
end
-
-
# for override
-
1
def quick_filter_list
-
[]
-
end
-
-
# for override
-
1
def custom_quick_filters
-
""
-
end
-
-
# @param data [Hash] the filter categories. The hash needs for every category
-
# a hash with a label and a input_field entry.
-
1
def filter_form data={}, sort_input_field=nil, form_args={}
-
haml :filter_form, categories: data,
-
sort_input_field: sort_input_field,
-
form_args: form_args
-
end
-
-
1
def filter_fields slot_selector: nil, sort_field: nil
-
form_args = { action: filter_action_path, class: "slotter" }
-
form_args["data-slot-selector"] = slot_selector if slot_selector
-
filter_form filter_form_data, sort_field, form_args
-
end
-
-
1
def filter_form_data
-
all_filter_keys.each_with_object({}) do |cat, h|
-
h[cat] = { label: filter_label(cat),
-
input_field: _render("filter_#{cat}_formgroup"),
-
active: active_filter?(cat),
-
default: default_filter?(cat) }
-
end
-
end
-
-
1
def active_filter? field
-
if card.filter_keys_from_params.present?
-
filter_hash.key? field
-
else
-
default_filter? field
-
end
-
end
-
-
1
def default_filter? field
-
card.default_filter_hash.key? field
-
end
-
-
1
def filter_label field
-
# return "Keyword" if field.to_sym == :name
-
#
-
filter_label_from_method(field) || filter_label_from_name(field)
-
end
-
-
1
def filter_label_from_method field
-
try "#{field}_filter_label"
-
end
-
-
1
def filter_label_from_name field
-
Card.fetch_name(field) { field.to_s.titleize }
-
end
-
-
1
def filter_action_path
-
path
-
end
-
-
1
view :sort_formgroup, cache: :never do
-
select_tag "sort",
-
options_for_select(sort_options, card.current_sort),
-
class: "pointer-select _filter-sort form-control",
-
"data-minimum-results-for-search": "Infinity"
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter/filter_form.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Filter;
-
# Set: Abstract (Filter, FormHelper)
-
#
-
1
module FormHelper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter/form_helper.rb"; end
-
1
include_set Abstract::FilterHelper
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :filter_name_formgroup, cache: :never do
-
text_filter :name
-
end
-
-
1
def select_filter field, default=nil, options=nil
-
options ||= filter_options field
-
options.unshift(["--", ""]) unless default
-
select_filter_tag field, default, options
-
end
-
-
1
def multiselect_filter field, default=nil, options=nil
-
options ||= filter_options field
-
multiselect_filter_tag field, default, options
-
end
-
-
1
def text_filter field, default=nil, opts={}
-
value = filter_param(field) || default
-
text_filter_with_name_and_value filter_name(field), value, opts
-
end
-
-
1
def text_filter_with_name_and_value name, value, opts
-
opts[:class] ||= "simple-text"
-
add_class opts, "form-control"
-
text_field_tag name, value, opts
-
end
-
-
1
def range_filter field, default={}, opts={}
-
add_class opts, "simple-text range-filter-subfield"
-
default ||= {}
-
output [range_sign(:from),
-
sub_text_filter(field, :from, default, opts),
-
range_sign(:to),
-
sub_text_filter(field, :to, default, opts)]
-
end
-
-
1
def range_sign side
-
dir = side == :from ? "right" : "left"
-
wrap_with :span, class: "input-group-prepend" do
-
fa_icon("chevron-circle-#{dir}", class: "input-group-text")
-
end
-
end
-
-
1
def sub_text_filter field, subfield, default={}, opts={}
-
name = "filter[#{field}][#{subfield}]"
-
value = filter_hash.dig(field, subfield) || default[subfield]
-
text_filter_with_name_and_value name, value, opts
-
end
-
-
1
def autocomplete_filter type_code, options_card=nil
-
options_card ||= Card::Name[type_code, :type, :by_name]
-
text_filter type_code, "", class: "#{type_code}_autocomplete",
-
"data-options-card": options_card
-
end
-
-
1
def multiselect_filter_tag field, default, options, html_options={}
-
html_options[:multiple] = true
-
select_filter_tag field, default, options, html_options
-
end
-
-
1
def select_filter_tag field, default, options, html_options={}
-
name = filter_name field, html_options[:multiple]
-
options = options_for_select options, (filter_param(field) || default)
-
normalize_select_filter_tag_html_options field, html_options
-
select_tag name, options, html_options
-
end
-
-
# alters html_options hash
-
1
def normalize_select_filter_tag_html_options field, html_options
-
pointer_suffix = html_options[:multiple] ? "multiselect" : "select"
-
add_class html_options, "pointer-#{pointer_suffix} filter-input #{field} " \
-
"_filter_input_field _no-select2 form-control"
-
# _no-select2 because select is initiated after filter is opened.
-
html_options[:id] = "filter-input-#{unique_id}"
-
end
-
-
1
def filter_name field, multi=false
-
"filter[#{field}]#{'[]' if multi}"
-
end
-
-
1
def filter_options field
-
raw = send("#{field}_options")
-
raw.is_a?(Array) ? raw : option_hash_to_array(raw)
-
end
-
-
1
def option_hash_to_array hash
-
hash.each_with_object([]) do |(key, value), array|
-
array << [key, value.to_s]
-
array
-
end
-
end
-
-
1
def type_options type_codename, order="asc", max_length=nil
-
Card.cache.fetch "#{type_codename}-TYPE-OPTIONS" do
-
res = Card.search type: type_codename, return: :name, sort: "name", dir: order
-
max_length ? (res.map { |i| [trim_option(i, max_length), i] }) : res
-
end
-
end
-
-
1
def trim_option option, max_length
-
option.size > max_length ? "#{option[0..max_length]}..." : option
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter/form_helper.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Filter;
-
# Set: Abstract (Filter, QueryConstruction)
-
#
-
# all filter keys in the order they were selected
-
1
module QueryConstruction;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter/query_construction.rb"; end
-
1
def all_filter_keys
-
@all_filter_keys ||= filter_keys_from_params | filter_keys
-
end
-
-
1
def filter_and_sort_cql
-
75
filter_cql.merge(sort_cql)
-
end
-
-
1
def filter_cql
-
75
return {} if filter_hash.empty?
-
-
filter_cql_from_params
-
end
-
-
# separate method is needed for tests
-
1
def filter_cql_from_params
-
filter_class.new(filter_keys_with_values, blocked_id_cql).to_cql
-
end
-
-
1
def sort_cql
-
75
sort_hash
-
end
-
-
1
def blocked_id_cql
-
not_ids = filter_param :not_ids
-
not_ids.present? ? { id: ["not in", not_ids.split(",")] } : {}
-
end
-
-
1
def current_sort
-
sort_param || default_sort_option
-
end
-
-
1
def default_sort_option
-
cql_content[:sort]
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/03_filter/query_construction.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (RightFilterForm)
-
#
-
# To be included in a field card to get a filter for the parent.
-
1
module RightFilterForm;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/04_right_filter_form.rb"; end
-
# The core view renders a filter for the left card.
-
-
1
include_set Set::Abstract::Filter
-
-
1
def virtual?
-
new?
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def filter_action_path
-
path mark: card.name.left, view: filter_view
-
end
-
-
1
view :core, cache: :never do
-
filter_fields slot_selector: filter_selector
-
end
-
-
1
def filter_view
-
:filter_result
-
end
-
-
1
def filter_selector
-
".#{filter_view}-view"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/04_right_filter_form.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Search)
-
#
-
1
module Search;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/05_search.rb"; end
-
1
include_set Abstract::Paging
-
1
include_set Abstract::SearchParams
-
1
include_set Abstract::Filter
-
-
1
def search _args={}
-
raise Error, "search not overridden"
-
end
-
-
1
def cached_search args={}
-
2
@search_results ||= {}
-
2
@search_results[args.to_s] ||= search args
-
end
-
-
1
def returning item, args
-
2
args[:return] = item
-
2
yield
-
end
-
-
1
def item_cards args={}
-
2
args[:limit] ||= 0
-
4
returning(:card, args) { search args }
-
end
-
-
1
def item_names args={}
-
args[:limit] ||= 0
-
returning(:name, args) { search args }
-
end
-
-
1
def item_ids args={}
-
args[:limit] ||= 0
-
returning(:id, args) { search args }
-
end
-
-
1
def count args={}
-
args[:offset] = 0
-
args[:limit] = 0
-
returning(:count, args) { search args }
-
end
-
-
# for override
-
1
def item_type
-
nil
-
end
-
-
1
def each_item_name_with_options _content=nil
-
options = {}
-
item = fetch_query.statement[:view]
-
options[:view] = item if item
-
item_names.each do |name|
-
yield name, options
-
end
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def search_with_params
-
2
search_with_rescue search_params
-
end
-
-
1
def count_with_params
-
search_with_rescue search_params.merge(return: :count)
-
end
-
-
1
def search_with_rescue query_args
-
2
card.cached_search query_args
-
rescue Error::BadQuery => e
-
Rails.logger.info "BadQuery: #{query_args}"
-
e
-
end
-
-
1
def implicit_item_view
-
view = voo_items_view || item_view_from_query || default_item_view
-
Card::View.normalize view
-
end
-
-
# override if query can specify item view
-
1
def item_view_from_query
-
nil
-
end
-
-
1
def with_results
-
1
return render_no_search_results if search_with_params.empty?
-
yield
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/05_search.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Search;
-
# Set: Abstract (Search, Views)
-
#
-
1
module Views;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/05_search/views.rb"; end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :search_count, cache: :never do
-
search_with_params.to_s
-
end
-
-
1
view :search_error, cache: :never do
-
sr_class = search_with_params.class.to_s
-
%(#{sr_class} :: #{search_with_params.message} :: #{card.content})
-
end
-
-
1
view :card_list, cache: :never do
-
if search_with_params.empty?
-
"no results"
-
else
-
search_with_params.map do |item_card|
-
nest_item item_card
-
end.join "\n"
-
end
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
AUTOCOMPLETE_LIMIT = 8 # number of name suggestions for autocomplete text fields
-
-
1
def item_cards
-
search_with_params
-
end
-
-
# NOCACHE because paging_urls is uncacheable hash and thus not safe to merge
-
1
view :molecule, cache: :never do
-
molecule.merge render_paging_urls
-
end
-
-
# TODO: design better autocomplete API
-
1
view :name_complete, cache: :never do
-
complete_search limit: AUTOCOMPLETE_LIMIT
-
end
-
-
1
view :name_match, cache: :never do
-
complete_or_match_search limit: AUTOCOMPLETE_LIMIT
-
end
-
-
1
def complete_or_match_search limit: AUTOCOMPLETE_LIMIT, start_only: false
-
starts_with = complete_search limit: limit
-
return starts_with if start_only
-
-
remaining_slots = limit - starts_with.size
-
return starts_with if remaining_slots.zero?
-
starts_with + match_search(not_names: starts_with, limit: remaining_slots)
-
end
-
-
1
def complete_search limit: AUTOCOMPLETE_LIMIT
-
card.search name_cql(limit).merge(complete_cql)
-
end
-
-
1
def match_search limit: AUTOCOMPLETE_LIMIT, not_names: []
-
card.search name_cql(limit).merge(match_cql(not_names))
-
end
-
-
1
def name_cql limit
-
{ limit: limit, sort: "name", return: "name" }
-
end
-
-
1
def complete_cql
-
{ complete: term_param }
-
end
-
-
1
def match_cql not_names
-
cql = { name_match: term_param }
-
cql[:name] = ["not in"] + not_names if not_names.any?
-
cql
-
end
-
-
1
def term_param
-
params[:term]
-
end
-
end
-
-
2
module DataFormat; module_parent.send :register_set_format, Card::Format::DataFormat, self; extend Card::Set::AbstractFormat
-
1
view :card_list do
-
search_with_params.map do |item_card|
-
nest_item item_card
-
end
-
end
-
end
-
-
2
module CsvFormat; module_parent.send :register_set_format, Card::Format::CsvFormat, self; extend Card::Set::AbstractFormat
-
1
view :core, :core, mod: All::AllCsv::CsvFormat
-
-
1
view :card_list do
-
items = super()
-
if depth.zero?
-
title_row + items
-
else
-
items
-
end
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :card_list, cache: :never do
-
1
with_results do
-
search_result_list "search-result-list" do |item_card|
-
card_list_item item_card
-
end
-
end
-
end
-
-
1
view :select_item, cache: :never do
-
wrap do
-
haml :select_item
-
end
-
end
-
-
1
before :select_item do
-
class_up "card-slot", "_filter-result-slot"
-
end
-
-
1
view :checkbox_list, cache: :never do
-
with_results do
-
search_result_list "_search-checkbox-list pr-2" do |item_card|
-
checkbox_item item_card
-
end
-
end
-
end
-
-
1
view :no_search_results do
-
1
wrap_with :div, "", class: "search-no-results"
-
end
-
-
1
private
-
-
1
def card_list_item item_card
-
nest_item item_card, size: voo.size do |rendered, item_view|
-
%(<div class="search-result-item item-#{item_view}">#{rendered}</div>)
-
end
-
end
-
-
1
def search_result_list klass
-
with_paging do
-
wrap_with :div, class: klass do
-
search_with_params.map do |item_card|
-
yield item_card
-
end
-
end
-
end
-
end
-
-
1
def checkbox_item item_card
-
subformat(item_card).wrap do
-
haml :checkbox_item, unique_id: unique_id, item_card: item_card
-
end
-
end
-
-
1
def closed_limit
-
[search_params[:limit].to_i, Card.config.closed_search_limit].min
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/05_search/views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (CqlSearch)
-
#
-
1
module CqlSearch;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/06_cql_search.rb"; end
-
1
include_set Abstract::Search
-
-
1
def search args={}
-
3
with_skipping args do
-
3
query = fetch_query(args)
-
# forces explicit limiting
-
# can be 0 or less to force no limit
-
3
raise "OH NO.. no limit" unless query.mods[:limit]
-
3
query.run
-
end
-
end
-
-
# for override, eg when required subqueries are known to be missing
-
1
def skip_search?
-
3
false
-
end
-
-
1
def with_skipping args
-
3
skip_search? ? skipped_search_result(args) : yield
-
end
-
-
1
def skipped_search_result args={}
-
args[:return] == :count ? 0 : []
-
end
-
-
1
def cache_query?
-
1388
true
-
end
-
-
1
def fetch_query args={}
-
3
@query = nil unless cache_query?
-
3
@query ||= {}
-
3
@query[args.to_s] ||= query(args.clone) # cache query
-
end
-
-
1
def query args={}
-
3
Query.new standardized_query_args(args), name
-
end
-
-
1
def standardized_query_args args
-
3
args = query_args(args).symbolize_keys
-
3
args[:context] ||= name
-
3
args
-
end
-
-
1
def cql_hash
-
1310
@cql_hash = nil unless cache_query?
-
1310
@cql_hash ||= cql_content.merge filter_and_sort_cql
-
end
-
-
# override this to define search
-
1
def cql_content
-
75
@cql_content = nil unless cache_query?
-
75
@cql_content ||= begin
-
75
query = content
-
75
query = query.is_a?(Hash) ? query : parse_json_query(query)
-
75
query.symbolize_keys
-
end
-
end
-
-
1
def query_args args={}
-
3
cql_hash.merge args
-
end
-
-
1
def parse_json_query query
-
75
empty_query_error! if query.empty?
-
75
JSON.parse query
-
rescue JSON::ParserError
-
raise Error::BadQuery, "Invalid JSON search query: #{query}"
-
end
-
-
1
def empty_query_error!
-
raise Error::BadQuery, "can't run search with empty content"
-
end
-
-
1
def item_type
-
1305
type = cql_hash[:type]
-
1305
return if type.is_a?(Array) || type.is_a?(Hash)
-
1301
type
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def default_limit
-
card_content_limit || super
-
end
-
-
1
def card_content_limit
-
1
card.cql_hash&.dig :limit
-
end
-
-
1
def item_view_from_query
-
query_with_params.statement[:item]
-
end
-
-
1
def query_with_params
-
@query_with_params ||= card.fetch_query search_params
-
end
-
-
1
def limit
-
query_with_params.limit
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def default_limit
-
1
card_content_limit || super
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/abstract/06_cql_search.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Children" cards
-
#
-
1
module Children;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/children.rb"; end
-
1
def raw_help_text
-
"Cards formed by \"mating\" {{_left|name}} with another card. "\
-
"eg: \"{{_left|name}}+mate\"."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/children.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Created" cards
-
#
-
1
module Created;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/created.rb"; end
-
1
def raw_help_text
-
"Cards created by {{_left|name}}."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/created.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Edited" cards
-
#
-
1
module Edited;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/edited.rb"; end
-
1
def raw_help_text
-
"Cards edited by {{_left|name}}."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/edited.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Editors" cards
-
#
-
1
module Editors;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/editors.rb"; end
-
1
def raw_help_text
-
"Users who have edited {{_left|name}}."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/editors.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Follow" cards
-
#
-
1
module Follow;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/follow.rb"; end
-
1
def raw_help_text
-
"Get notified about changes"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/follow.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+LinkedToBy" cards
-
#
-
1
module LinkedToBy;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/linked_to_by.rb"; end
-
1
def raw_help_text
-
"Cards that link to {{_left|name}}."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/linked_to_by.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+LinksTo" cards
-
#
-
# -*- encoding : utf-8 -*-
-
1
module LinksTo;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/links_to.rb"; end
-
-
1
def raw_help_text
-
"Cards that <em>{{_left|name}}</em> links to."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/links_to.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Mates" cards
-
#
-
1
module Mates;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/mates.rb"; end
-
1
def raw_helo_text
-
"If there is a card named \"X+{{_left|name}}\", then X is a mate of {{_left|name}}."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/mates.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+NestedBy" cards
-
#
-
1
module NestedBy;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/nested_by.rb"; end
-
1
def raw_help_text
-
"Cards that include {{_left|name}}."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/nested_by.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Nests" cards
-
#
-
1
module Nests;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/nests.rb"; end
-
1
def raw_help_text
-
"Cards that {{_left|name}} includes."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/nests.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+ReferredToBy" cards
-
#
-
1
module ReferredToBy;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/referred_to_by.rb"; end
-
1
def raw_help_text
-
"Cards that refer to {{_left|name}}."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/referred_to_by.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+RefersTo" cards
-
#
-
1
module RefersTo;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/right/refers_to.rb"; end
-
1
def raw_help_text
-
"Cards that {{_left|name}} refers to."
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/right/refers_to.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Recent"
-
#
-
1
module Recent;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/self/recent.rb"; end
-
1
ACTS_PER_PAGE = 25
-
-
1
view :title do
-
23
voo.title ||= "Recent Changes"
-
23
super()
-
end
-
-
1
def recent_acts
-
action_relation = qualifying_actions.where "card_acts.id = card_act_id"
-
Act.where("EXISTS (#{action_relation.to_sql})").order id: :desc
-
end
-
-
1
def qualifying_actions
-
Action.all_viewable.where "draft is not true"
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
voo.hide :history_legend unless voo.main
-
@acts_per_page = ACTS_PER_PAGE
-
acts_layout card.recent_acts, :absolute
-
end
-
end
-
-
2
module RssFormat; module_parent.send :register_set_format, Card::Format::RssFormat, self; extend Card::Set::AbstractFormat
-
1
view :feed_item_description do
-
render_blank
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
def items_for_export
-
card.item_cards limit: 20
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/self/recent.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Search"
-
#
-
1
module Search;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/self/search.rb"; end
-
1
def query_args args={}
-
return super unless keyword_contains_cql? args
-
args.merge parse_keyword_cql(args)
-
end
-
-
1
def parse_keyword_cql args
-
parse_json_query(args[:vars][:keyword])
-
end
-
-
1
def keyword_contains_cql? hash
-
hash[:vars] && (keyword = hash[:vars][:keyword]) && keyword =~ /^\{.+\}$/
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :search_error, cache: :never do
-
sr_class = search_with_params.class.to_s
-
-
# don't show card content; not very helpful in this case
-
%(#{sr_class} :: #{search_with_params.message})
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :title, cache: :never do
-
return super() unless (keyword = search_keyword) &&
-
(title = keyword_search_title(keyword))
-
voo.title = title
-
end
-
-
1
def keyword_search_title keyword
-
%(Search results for: <span class="search-keyword">#{h keyword}</span>)
-
end
-
-
1
def search_keyword
-
(vars = search_vars) && vars[:keyword]
-
rescue Card::Error::PermissionDenied
-
nil
-
end
-
-
1
def search_vars
-
root.respond_to?(:search_params) ? root.search_params[:vars] : search_params[:vars]
-
end
-
-
1
def cql_search?
-
card.keyword_contains_cql? vars: search_vars
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
view :complete, cache: :never do
-
term = term_param
-
exact = Card.fetch term, new: {}
-
-
{
-
search: true,
-
term: term,
-
add: add_item(exact),
-
new: new_item_of_type(exact),
-
goto: goto_items(term, exact)
-
}
-
end
-
-
1
def add_item exact
-
return unless exact.new_card? &&
-
exact.name.valid? &&
-
!exact.virtual? &&
-
exact.ok?(:create)
-
[h(exact.name), exact.name.url_key]
-
end
-
-
1
def new_item_of_type exact
-
return unless (exact.type_id == CardtypeID) &&
-
Card.new(type_id: exact.id).ok?(:create)
-
[exact.name, "new/#{exact.name.url_key}"]
-
end
-
-
1
def goto_items term, exact
-
goto_names = complete_or_match_search start_only: Card.config.navbox_match_start_only
-
goto_names.unshift exact.name if add_exact_to_goto_names? exact, goto_names
-
goto_names.map do |name|
-
[name, name.to_name.url_key, h(highlight(name, term, sanitize: false))]
-
end
-
end
-
-
1
def add_exact_to_goto_names? exact, goto_names
-
exact.known? && !goto_names.find { |n| n.to_name.key == exact.key }
-
end
-
-
1
def term_param
-
term = query_params[:keyword]
-
if (term =~ /^\+/) && (main = params["main"])
-
term = main + term
-
end
-
term
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/self/search.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "SearchType" cards
-
#
-
1
module SearchType;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-search/set/type/search_type.rb"; end
-
1
include_set Type::Json
-
1
include_set Abstract::CqlSearch
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :core, cache: :never do
-
_render search_result_view
-
end
-
-
1
def chunk_list
-
20
:query
-
end
-
-
1
def search_result_view
-
1
case search_with_params
-
when Exception then :search_error
-
when Integer then :search_count
-
when nest_mode == :template then :raw
-
1
else :card_list
-
end
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
def items_for_export
-
return [] if card.content.empty? || unexportable_tag?(card.name.tag_name.key)
-
card.item_cards
-
end
-
-
# avoid running the search from +:content_options (huge results)
-
# and +:structure (errors)
-
# TODO: make this configurable in set mods
-
1
def unexportable_tag? tag_key
-
%i[content_options structure].map { |code| code.cardname.key }.include? tag_key
-
end
-
end
-
-
2
module RssFormat; module_parent.send :register_set_format, Card::Format::RssFormat, self; extend Card::Set::AbstractFormat
-
1
view :feed_body do
-
case raw_feed_items
-
when Exception then @xml.item(render!(:search_error))
-
when Integer then @xml.item(render!(:search_count))
-
else super()
-
end
-
end
-
-
1
def raw_feed_items
-
@raw_feed_items ||= search_with_params
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
1
_render search_result_view
-
end
-
-
1
view :bar do
-
voo.hide :one_line_content
-
super()
-
end
-
-
1
view :one_line_content, cache: :never do
-
if depth > max_depth
-
"..."
-
else
-
search_params[:limit] = closed_limit
-
_render_core hide: "paging", items: { view: :link }
-
# TODO: if item is queryified to be "name", then that should work.
-
# otherwise use link
-
end
-
end
-
-
1
def rss_link_tag
-
path_opts = { format: :rss }
-
Array(search_params[:vars]).compact.each { |k, v| opts["_#{k}"] = v }
-
tag "link", rel: "alternate",
-
type: "application/rss+xml",
-
title: "RSS",
-
href: path(path_opts)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-search/set/type/search_type.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Comment)
-
#
-
1
module Comment;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/comment.rb"; end
-
1
def commenting?
-
323
comment && action != :delete
-
end
-
-
1
event :add_comment, :prepare_to_store, on: :save, when: :comment do
-
Env.session[:comment_author] = comment_author if Env.session
-
return unless comment.present?
-
self.content =
-
[content, format.comment_with_signature].compact.join "\n<hr\>\n"
-
self.comment = nil
-
end
-
-
1
attr_writer :comment_author
-
-
1
def comment_author
-
@comment_author ||=
-
Env.session[:comment_author] || Env.params[:comment_author] || "Anonymous"
-
end
-
-
1
def clean_comment
-
comment.split(/\n/).map do |line|
-
"<p>#{line.strip.empty? ? ' ' : line}</p>"
-
end * "\n"
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def comment_with_signature
-
card.clean_comment + "\n" + comment_signature
-
end
-
-
1
def comment_signature
-
wrap_with :div, class: "w-comment-author" do
-
"#{comment_author}.....#{Time.zone.now}"
-
end
-
end
-
-
1
def comment_author
-
if Auth.signed_in?
-
"[[#{Auth.current.name}]]"
-
else
-
"#{card.comment_author} (Not signed in)"
-
end
-
end
-
-
1
view :comment_box, denial: :blank, unknown: true, perms: :update do
-
wrap_with :div, class: "comment-box nodblclick" do
-
action = card.new_card? ? :create : :update
-
card_form action do
-
[hidden_comment_fields, comment_box, comment_buttons]
-
end
-
end
-
end
-
-
1
def hidden_comment_fields
-
return unless card.new_card?
-
hidden_field_tag "card[name]", card.name
-
# FIXME: wish we had more generalized solution for names.
-
# without this, nonexistent cards will often take left's linkname.
-
# (needs test)
-
end
-
-
1
def comment_box
-
text_area :comment, rows: 3
-
end
-
-
1
def comment_buttons
-
wrap_with :div, class: "comment-buttons" do
-
[comment_author_label, comment_submit_button]
-
end
-
end
-
-
1
def comment_author_label
-
return if Auth.signed_in?
-
%(<label>My Name is:</label> #{text_field :comment_author})
-
end
-
-
1
def comment_submit_button
-
submit_button text: "Comment", type: :submit, disable_with: "Commenting"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/comment.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Error)
-
#
-
1
module Error;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/error.rb"; end
-
1
def copy_errors card
-
card.errors.each do |att, msg|
-
errors.add att, msg
-
end
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :compact_missing, perms: :none, compact: true do
-
""
-
end
-
-
1
view :unknown, perms: :none, cache: :never do
-
""
-
end
-
-
1
view :server_error, perms: :none do
-
tr(:server_error)
-
end
-
-
1
view :denial, perms: :none do
-
focal? ? tr(:denial) : ""
-
end
-
-
1
view :not_found, perms: :none do
-
error_name = card.name.present? ? safe_name : tr(:not_found_no_name)
-
tr(:not_found_named, cardname: error_name)
-
end
-
-
1
view :bad_address, perms: :none do
-
1
root.error_status = 404
-
1
tr(:bad_address)
-
end
-
-
1
view :errors do
-
["Problem:", "", standard_errors].flatten.join "\n"
-
end
-
-
1
def standard_errors
-
card.errors.map do |attrib, msg|
-
attrib == :abort ? msg : standard_error_message(attrib, msg)
-
end
-
end
-
-
# for override
-
1
def standard_error_message attribute, message
-
"#{attribute.to_s.upcase}: #{message}"
-
end
-
-
1
def unsupported_view_error_message view
-
tr(:unsupported_view, view: view, cardname: card.name)
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
view :errors do
-
format_error error_list
-
end
-
-
1
view :server_error, :errors
-
1
view :denial, :errors
-
1
view :not_found, :errors
-
-
1
view :bad_address do
-
format_error super()
-
end
-
-
1
def format_error error
-
{ error_status: error_status, errors: error }
-
end
-
-
1
def error_list
-
card.errors.each_with_object([]) do |(field, message), list|
-
list << { field: field, message: message }
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/error.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Links)
-
#
-
1
module Links;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/links.rb"; end
-
1
RESOURCE_TYPE_REGEXP = /^([a-zA-Z][\-+\.a-zA-Z\d]*):/
-
-
# The #link_to methods support smart formatting of links in multiple formats.
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
# Creates a "link", the meaning of which depends upon the format. In this base
-
# format, the link looks like [text][absolute path]
-
#
-
# @param text [String] optional string associated with link
-
# @param opts [Hash] optional Hash. In simple formats, :path is usually the only key
-
1
def link_to text=nil, opts={}
-
26
path = path((opts.delete(:path) || {}))
-
26
if text && path != text
-
"#{text}[#{path}]"
-
else
-
26
path
-
end
-
end
-
-
# link to a different view of the current card
-
# @param view [Symbol,String]
-
# @param text [String]
-
# @param opts [Hash]
-
1
def link_to_view view, text=nil, opts={}
-
49
add_to_path opts, view: view unless view == :home
-
49
link_to text, opts
-
end
-
-
# link to a card other than the current card.
-
# @param cardish [Integer, Symbol, String, Card] a card identifier
-
# @param text [String]
-
# @param opts [Hash]
-
1
def link_to_card cardish, text=nil, opts={}
-
197
add_to_path opts, mark: Card::Name[cardish]
-
197
link_to text, opts
-
end
-
-
# a "resource" is essentially a reference to something that
-
# decko doesn't recognize to be a card. Can be a remote url,
-
# a local url (that decko hasn't parsed) or a local path.
-
# @param resource [String]
-
# @param text [String]
-
# @param opts [Hash]
-
1
def link_to_resource resource, text=nil, opts={}
-
95
resource = clean_resource resource, resource_type(resource)
-
95
link_to text, opts.merge(path: resource)
-
end
-
-
# smart_link_to is wrapper method for #link_to, #link_to_card, #link_to_view, and
-
# #link_to_resource. If the opts argument contains :view, :related, :card, or
-
# :resource, it will use the respective method to render a link.
-
#
-
# This is usually most useful when writing views that generate many different
-
# kinds of links.
-
1
def smart_link_to text, opts={}
-
if (linktype = %i[view card resource].find { |key| opts[key] })
-
send "link_to_#{linktype}", opts.delete(linktype), text, opts
-
else
-
send :link_to, text, opts
-
end
-
end
-
-
1
private
-
-
1
def resource_type resource
-
164
case resource
-
48
when /^https?\:/ then "external-link"
-
116
when %r{^/} then "internal-link"
-
when /^mailto\:/ then "email-link"
-
when RESOURCE_TYPE_REGEXP then Regexp.last_match(1) + "-link"
-
end
-
end
-
-
1
def clean_resource resource, resource_type
-
95
if resource_type == "internal-link"
-
70
contextualize_path resource[1..-1]
-
else
-
25
resource
-
end
-
end
-
-
1
def add_to_path opts, new_hash
-
246
opts[:path] = (opts[:path] || {}).merge new_hash
-
end
-
end
-
-
1
public
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# in HTML, #link_to renders an anchor tag <a>
-
# it treats opts other than "path" as html opts for that tag,
-
# and it adds special handling of "remote" and "method" opts
-
# (changes them into data attributes)
-
1
def link_to text=nil, opts={}
-
360
opts[:href] ||= path opts.delete(:path)
-
360
text = raw(text || opts[:href])
-
360
interpret_data_opts_to_link_to opts
-
360
wrap_with :a, text, opts
-
end
-
-
# in HTML, #link_to_card adds special css classes indicated whether a
-
# card is "known" (real or virtual) or "wanted" (unknown)
-
# TODO: upgrade from (known/wanted)-card to (real/virtual/unknown)-card
-
1
def link_to_card cardish, text=nil, opts={}
-
197
name = Card::Name[cardish]
-
197
slotterify opts if opts[:slotter]
-
197
add_known_or_wanted_class opts, name
-
197
super name, (text || name), opts
-
end
-
-
# in HTML, #link_to_view defaults to a remote link with rel="nofollow".
-
1
def link_to_view view, text=nil, opts={}
-
49
slotterify opts
-
49
super view, (text || view), opts
-
end
-
-
# in HTML, #link_to_resource automatically adds a target to external resources
-
# so they will open in another tab. It also adds css classes indicating whether
-
# the resource is internal or external
-
1
def link_to_resource resource, text=nil, opts={}
-
69
add_resource_opts opts, resource_type(resource)
-
69
super
-
end
-
-
1
private
-
-
1
def slotterify opts
-
61
opts.delete(:slotter)
-
61
opts.reverse_merge! remote: true, rel: "nofollow"
-
61
add_class opts, "slotter"
-
end
-
-
1
def add_known_or_wanted_class opts, name
-
197
known = opts.delete :known
-
197
known = Card.known?(name) if known.nil?
-
197
add_class opts, (known ? "known-card" : "wanted-card")
-
end
-
-
1
def interpret_data_opts_to_link_to opts
-
360
%i[remote method].each do |key|
-
720
next unless (val = opts.delete key)
-
62
opts["data-#{key}"] = val
-
end
-
end
-
-
1
def add_resource_opts opts, resource_type
-
69
opts[:target] ||= "_blank" if resource_type == "external-link"
-
69
add_class opts, resource_type
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/links.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (ListChanges)
-
#
-
# -*- encoding : utf-8 -*-
-
1
module ListChanges;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/list_changes.rb"; end
-
-
1
def list_fields
-
19
Card.search({ left: name, type_id: Card::MirroredListID }, "list fields")
-
end
-
-
1
def listed_by_fields
-
19
Card.search({ left: name, type_id: Card::MirrorListID }, "listed by fields")
-
end
-
-
1
def linker_lists
-
197
Card.search({ type_id: Card::MirroredListID, link_to: name },
-
"lists that link to #{name}")
-
end
-
-
1
def codename_list_exist?
-
216
Card::Codename.exists?(:mirrored_list) && Card::Codename.exists?(:mirror_list)
-
end
-
-
1
event :trunk_cardtype_of_a_list_relation_changed, :finalize,
-
changed: :type, on: :update, when: :codename_list_exist? do
-
1
type_key_was = Card.quick_fetch(type_id_before_act)&.key
-
-
1
list_fields.each do |card|
-
card.update_listed_by_cache_for card.item_keys, type_key: type_key_was
-
card.update_listed_by_cache_for card.item_keys
-
end
-
1
listed_by_fields.each &:update_cached_list
-
end
-
-
1
event :trunk_name_of_a_list_relation_changed, :finalize,
-
changed: :name, on: :update,
-
when: :codename_list_exist? do
-
18
list_fields.each do |card|
-
card.update_listed_by_cache_for card.item_keys
-
end
-
18
listed_by_fields.each &:update_cached_list
-
end
-
-
1
event :cardtype_of_list_item_changed, :validate,
-
changed: :type, on: :save,
-
when: :codename_list_exist? do
-
197
linker_lists.each do |card|
-
next unless card.item_type_id != type_id
-
errors.add(:type,
-
"can't be changed because #{name} " \
-
"is referenced by list card #{card.name}")
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/list_changes.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Path)
-
#
-
1
module Path;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/path.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
# Decko uses "path" a bit unusually. In most formats, it returns a full url. In HTML,
-
# it provides everything after the domain/port.
-
#
-
# If you're feeling your saucy oats, you might point out that typically "paths" don't
-
# include queries and fragment identifiers, much less protocols, domains, and ports.
-
# 10 pedantry points to you! But "path" has just four letters and is smart about
-
# format needs, so using it will lead you down the right ... something or other.
-
-
# Format#path is for generating standard card routes, eg, assuming the card
-
# associated with the current format is named "current", it will generate paths like
-
# these:
-
-
# path view: :bar -> "current?view=bar"
-
# path mark: [mycardid] -> "mycardname"
-
# path format: :csv) -> "current.csv"
-
# path action: :update -> "update/current"
-
-
# #path produces paths that follow one of three main patterns:
-
-
# 1. mark[.format][?query] # standard GET request
-
# 2. action/mark[?query] # GET variant of standard actions
-
# 3. new/mark # shortcut for "new" view of cardtype
-
-
# @param opts [Hash, String] a String is treated as a complete path and
-
# bypasses all processing
-
# @option opts [String, Card::Name, Integer, Symbol, Card] :mark
-
# @option opts [Symbol] :action card action (:create, :update, :delete)
-
# @option opts [Symbol] :format
-
# @option opts [Hash] :card
-
# @option opts [TrueClass] :no_mark
-
-
1
CAST_PARAMS = { slot: { hide: :array, show: :array, wrap: :array } }.freeze
-
# TODO: monkey API for this
-
-
1
def path opts={}
-
463
return opts unless opts.is_a? Hash
-
355
path = new_cardtype_path(opts) || standard_path(opts)
-
355
contextualize_path path
-
end
-
-
# in base format (and therefore most other formats), even internal paths
-
# are rendered as absolute urls.
-
1
def contextualize_path relative_path
-
3
card_url relative_path
-
end
-
-
1
private
-
-
1
def new_cardtype_path opts
-
355
return unless valid_opts_for_new_cardtype_path? opts
-
15
"#{opts.delete :action}/#{path_mark opts}#{path_query opts}"
-
end
-
-
1
def valid_opts_for_new_cardtype_path? opts
-
355
return unless opts[:action].in? %i[new type]
-
-
# "new" and "type" are not really an action and are only
-
# a valid value here for this path
-
15
opts[:mark].present?
-
end
-
-
1
def standard_path opts
-
340
path_base(opts) + path_extension(opts) + path_query(opts)
-
end
-
-
1
def path_base opts
-
340
mark = path_mark opts
-
340
if (action = path_action opts)
-
39
action_base action, mark
-
else
-
301
mark
-
end
-
end
-
-
1
def action_base action, mark
-
39
mark.present? ? "#{action}/#{mark}" : "card/#{action}"
-
# the card/ prefix prevents interpreting action as cardname
-
end
-
-
1
def path_action opts
-
340
return unless (action = opts.delete(:action)&.to_sym)
-
124
%i[create update delete].find { |a| a == action }
-
end
-
-
1
def path_mark opts
-
355
return "" if markless_path? opts
-
347
name = opts[:mark] ? Card::Name[opts.delete(:mark)] : card.name
-
347
add_unknown_name_to_opts name.to_name, opts
-
347
name.to_name.url_key
-
end
-
-
1
def markless_path? opts
-
355
opts[:action] == :create || opts.delete(:no_mark)
-
end
-
-
1
def path_extension opts
-
340
extension = opts.delete :format
-
340
extension ? ".#{extension}" : ""
-
end
-
-
1
def path_query opts
-
355
opts = cast_path_opts opts
-
355
opts.empty? ? "" : "?#{opts.to_param}"
-
end
-
-
# normalizes certain path opts to specified data types
-
1
def cast_path_opts opts, cast_hash=nil
-
355
cast_hash ||= CAST_PARAMS
-
355
return opts unless opts.is_a?(::Hash)
-
355
opts.each do |key, value|
-
105
next unless (cast_to = cast_hash[key])
-
opts[key] = cast_path_value value, cast_to
-
end
-
end
-
-
1
def cast_path_value value, cast_to
-
if cast_to.is_a? Hash
-
cast_path_opts value, cast_to
-
else
-
send "cast_path_value_as_#{cast_to}", value
-
end
-
end
-
-
1
def cast_path_value_as_array value
-
Array.wrap value
-
end
-
-
1
def add_unknown_name_to_opts name, opts
-
347
return if name_specified?(opts) || name_standardish?(name) || Card.known?(name)
-
opts[:card] ||= {}
-
opts[:card][:name] = name
-
end
-
-
1
def name_specified? opts
-
347
opts[:card] && opts[:card][:name]
-
end
-
-
# no name info will be lost by using url_key
-
1
def name_standardish? name
-
347
name.s == Card::Name.url_key_to_standard(name.url_key)
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
def add_unknown_name_to_opts name, opts
-
# noop
-
end
-
end
-
-
2
module CssFormat; module_parent.send :register_set_format, Card::Format::CssFormat, self; extend Card::Set::AbstractFormat
-
1
def contextualize_path relative_path
-
24
if Card.config.file_storage == :local
-
# absolute paths lead to invalid assets path in css for cukes
-
24
card_path relative_path
-
else
-
# ...but relative paths are problematic when machine output and
-
# hard-coded assets (like fonts) are on different servers
-
card_url relative_path
-
end
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# in HTML, decko paths rendered as relative to the site's root.
-
1
def contextualize_path relative_path
-
418
card_path relative_path
-
end
-
end
-
-
2
module EmailHtmlFormat; module_parent.send :register_set_format, Card::Format::EmailHtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def contextualize_path relative_path
-
6
card_url relative_path
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/path.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (RichHtml)
-
#
-
1
module RichHtml;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
delegate :class_up, :class_down, :with_class_up, :without_upped_class, :classy,
-
to: :voo
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Alert)
-
#
-
1
module Alert;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/alert.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# alert_types: 'success', 'info', 'warning', 'danger'
-
1
def alert alert_type, dismissable=false, disappear=false, args={}
-
11
add_class args, alert_classes(alert_type, dismissable, disappear)
-
11
wrap_with :div, args.merge(role: "alert") do
-
11
[(alert_close_button if dismissable), output(yield)]
-
end
-
end
-
-
1
def alert_classes alert_type, dismissable, disappear
-
11
classes = ["alert", "alert-#{alert_type}"]
-
11
classes << "alert-dismissible " if dismissable
-
11
classes << "_disappear" if disappear
-
11
classy classes
-
end
-
-
1
def alert_close_button
-
11
wrap_with :button, type: "button", "data-dismiss": "alert",
-
class: "close", "aria-label": "Close" do
-
11
wrap_with :span, "×", "aria-hidden" => true
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/alert.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Content)
-
#
-
1
module Content;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/content.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def prepare_content_slot
-
25
class_up "card-slot", "d0-card-content"
-
25
voo.hide :menu
-
end
-
-
26
before(:content) { prepare_content_slot }
-
-
1
view :content do
-
24
voo.hide :edit_button
-
24
wrap do
-
24
[_render_menu, _render_core, _render_edit_button(edit: :inline)]
-
end
-
end
-
-
1
before(:content_with_edit_button) do
-
prepare_content_slot
-
end
-
-
1
view :content_with_edit_button do
-
wrap do
-
[_render_menu, _render_core, _render_edit_button(edit: :inline)]
-
end
-
end
-
-
1
view :short_content, wrap: { div: { class: "text-muted" } } do
-
25
short_content
-
end
-
-
1
view :raw_one_line_content, unknown: :mini_unknown,
-
wrap: { div: { class: "text-muted" } } do
-
raw_one_line_content
-
end
-
-
1
view :one_line_content, unknown: :mini_unknown,
-
wrap: { div: { class: "text-muted" } } do
-
one_line_content
-
end
-
-
1
before(:content_with_title) { prepare_content_slot }
-
-
1
view :content_with_title do
-
wrap true, title: card.format(:text).render_core do
-
[_render_menu, _render_core]
-
end
-
end
-
-
1
before :content_panel do
-
prepare_content_slot
-
class_up "card-slot", "card"
-
end
-
-
1
view :content_panel do
-
wrap do
-
wrap_with :div, class: "card-body" do
-
[_render_menu, _render_core]
-
end
-
end
-
end
-
-
1
view :titled do
-
@content_body = true
-
wrap do
-
[
-
naming { render_header },
-
render_flash,
-
wrap_body { render_titled_content },
-
render_comment_box(optional: :hide)
-
]
-
end
-
end
-
-
1
view :labeled, unknown: true do
-
@content_body = true
-
wrap(true, class: "row") do
-
labeled(render_title, wrap_body { "#{render_menu}#{render_labeled_content}" } )
-
end
-
end
-
-
1
def labeled label, content
-
haml :labeled, label: label, content: content
-
end
-
-
1
def labeled_field field, item_view=:name, opts={}
-
opts[:title] ||= Card.fetch_name field
-
field_nest field, opts.merge(view: :labeled,
-
items: (opts[:items] || {}).merge(view: item_view))
-
end
-
-
1
view :open do
-
4
toggle_logic
-
4
@toggle_mode = :open
-
4
@content_body = true
-
4
frame do
-
4
[_render_open_content, render_comment_box(optional: :hide)]
-
end
-
end
-
-
1
view :closed do
-
1
with_nest_mode :compact do
-
1
toggle_logic
-
1
class_up "d0-card-body", "closed-content"
-
1
@content_body = false
-
1
@toggle_mode = :close
-
1
frame
-
end
-
end
-
-
1
def toggle_logic
-
5
show_view?(:title_link, :hide) ? voo.show(:icon_toggle) : voo.show(:title_toggle)
-
end
-
-
1
def current_set_card
-
set_name = params[:current_set]
-
set_name ||= "#{card.name}+*type" if card.known? && card.type_id == Card::CardtypeID
-
set_name ||= "#{card.name}+*self"
-
Card.fetch(set_name)
-
end
-
-
1
def raw_one_line_content
-
cleaned = Card::Content.clean! render_raw, {}
-
cut_with_ellipsis cleaned
-
end
-
-
1
def one_line_content
-
# TODO: use a version of Card::Content.smart_truncate
-
# that counts characters instead of clean!
-
cleaned = Card::Content.clean! render_core, {}
-
cut_with_ellipsis cleaned
-
end
-
-
# LOCALIZE
-
1
def short_content
-
23
short_content_items || short_content_fields || short_content_from_core
-
end
-
-
1
def short_content_items
-
23
return unless card.respond_to? :count
-
"#{count} #{'item'.pluralize count}"
-
end
-
-
1
def short_content_fields
-
23
with_short_content_fields do |num_fields|
-
"#{num_fields} #{'field'.pluralize num_fields}" if num_fields.positive?
-
end
-
end
-
-
1
def with_short_content_fields
-
23
yield nested_field_names.size if voo.structure || card.structure
-
end
-
-
1
def short_content_from_core
-
23
content = render_core
-
3
if content.blank?
-
1
"empty"
-
2
elsif content.size <= 5
-
content
-
2
elsif content.count("\n") < 2
-
2
"#{content.size} characters"
-
else
-
"#{content.count("\n") + 1} lines"
-
end
-
end
-
-
1
def count
-
@count ||= card.count
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/content.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Error)
-
#
-
1
module Error;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/error.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :server_error, template: :haml
-
-
1
view :debug_server_error, wrap: { modal: { size: :full } } do
-
error_page = BetterErrors::ErrorPage.new Card::Error.current,
-
"PATH_INFO" => request.env["REQUEST_URI"]
-
haml :debug_server_error, {}, error_page
-
end
-
-
1
view :unknown do
-
6
createable { wrap { unknown_link "#{unknown_icon} #{render_title}" } }
-
end
-
-
# icon only, no wrap
-
1
view :mini_unknown, unknown: true, cache: :never do
-
createable { unknown_link unknown_icon }
-
end
-
-
1
def createable
-
2
card.ok?(:create) ? yield : ""
-
end
-
-
1
def unknown_link text
-
2
path_opts = voo.type ? { card: { type: voo.type } } : {}
-
2
link_to_view :new_in_modal, text, path: path_opts, class: classy("unknown-link")
-
end
-
-
1
def unknown_icon
-
2
fa_icon "plus-square"
-
end
-
-
1
view :compact_missing, perms: :none do
-
wrap_with :span, h(title_in_context), class: "text-muted"
-
end
-
-
1
view :conflict, cache: :never do
-
actor_link = link_to_card card.last_action.act.actor.name
-
class_up "card-slot", "error-view"
-
wrap do # LOCALIZE
-
alert "warning" do
-
%(
-
<strong>Conflict!</strong>
-
<span class="new-current-revision-id">#{card.last_action_id}</span>
-
<div>#{actor_link} has also been making changes.</div>
-
<div>Please examine below, resolve above, and re-submit.</div>
-
#{render_act}
-
)
-
end
-
end
-
end
-
-
1
view :errors, perms: :none do
-
2
return if card.errors.empty?
-
-
2
voo.title = card.name.blank? ? "Problems" : tr(:problems_name, cardname: card.name)
-
2
voo.hide! :menu
-
2
class_up "alert", "card-error-msg"
-
2
standard_errors voo.title
-
end
-
-
1
view :not_found do
-
2
voo.hide! :menu
-
2
voo.title = "Not Found"
-
2
frame do
-
2
[not_found_errors, sign_in_or_up_links("to create it")]
-
end
-
end
-
-
1
view :denial do
-
5
focal? ? loud_denial : quiet_denial
-
end
-
-
1
def view_for_unknown view
-
4
main? && ok?(:create) ? :new : super
-
end
-
-
1
def show_all_errors?
-
# make configurable by env
-
2
Auth.always_ok? || Rails.env.development?
-
end
-
-
1
def error_cardname exception
-
2
cardname = super
-
2
show_all_errors? ? backtrace_link(cardname, exception) : cardname
-
end
-
-
1
def rendering_error exception, view
-
6
wrap_with(:span, class: "render-error alert alert-danger") { super }
-
end
-
-
1
def error_modal_id
-
@error_modal_id ||= unique_id
-
end
-
-
1
def error_message exception
-
%{
-
<h3>Error message (visible to admin only)</h3>
-
<p><strong>#{CGI.escapeHTML exception.message}</strong></p>
-
<div>#{exception.backtrace * "<br>\n"}</div>
-
}
-
end
-
-
1
def backtrace_link cardname, exception
-
# TODO: make this a modal link after new modal handling is merged in
-
wrap_with(:span, title: error_message(exception)) { cardname }
-
end
-
-
1
def standard_errors heading=nil
-
3
alert "warning", true do
-
[
-
3
(wrap_with(:h4, heading, class: "alert-heading error") if heading),
-
error_messages.join("<hr>")
-
]
-
end
-
end
-
-
1
def error_messages
-
3
card.errors.map do |attrib, msg|
-
3
attrib == :abort ? h(msg) : standard_error_message(attrib, msg)
-
end
-
end
-
-
1
def standard_error_message attribute, message
-
3
"<p><strong>#{h attribute.to_s.upcase}:</strong> #{h message}</p>"
-
end
-
-
1
def not_found_errors
-
2
if card.errors.any?
-
1
standard_errors
-
else
-
1
haml :not_found
-
end
-
end
-
-
1
def sign_in_or_up_links to_task
-
6
return if Auth.signed_in?
-
-
6
links = [signin_link, signup_link].compact.join " #{tr :or} "
-
6
wrap_with(:div) do
-
6
[tr(:please), links, to_task].join(" ") + "."
-
end
-
end
-
-
1
def signin_link
-
6
link_to_card :signin, tr(:sign_in),
-
class: "signin-link", slotter: true, path: { view: :open }
-
end
-
-
1
def signup_link
-
6
return unless signup_ok?
-
-
6
link_to_card :signup, tr(:sign_up),
-
class: "signup-link", slotter: true, path: { action: :new }
-
end
-
-
1
def signup_ok?
-
6
Card.new(type_id: Card::SignupID).ok? :create
-
end
-
-
1
def quiet_denial
-
wrap_with :span, class: "denied" do
-
"<!-- Sorry, you don't have permission (#{@denied_task}) -->"
-
end
-
end
-
-
1
def loud_denial
-
5
voo.hide :menu
-
5
frame do
-
5
[wrap_with(:h1, tr(:sorry)),
-
wrap_with(:div, loud_denial_message)]
-
end
-
end
-
-
1
def loud_denial_message
-
5
to_task = @denied_task ? tr(:denied_task, denied_task: @denied_task) : tr(:to_do_that)
-
-
case
-
5
when not_denied_task_read?
-
tr(:read_only)
-
when Auth.signed_in?
-
1
tr(:need_permission_task, task: to_task)
-
else
-
4
Env.save_interrupted_action request.env["REQUEST_URI"]
-
4
sign_in_or_up_links to_do_unauthorized_task
-
end
-
end
-
-
1
def not_denied_task_read?
-
5
@denied_task != :read && Card.config.read_only
-
end
-
-
1
def to_do_unauthorized_task
-
4
@denied_task ? tr(:denied_task, denied_task: @denied_task) : tr(:to_do_that)
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/error.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Frame)
-
#
-
1
module Frame;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/frame.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :flash, cache: :never, unknown: true, perms: :none do
-
20
flash_notice = params[:flash] || Env.success.flash
-
20
return "" unless flash_notice.present? && focal?
-
-
Array(flash_notice).join "\n"
-
end
-
-
1
def frame &block
-
20
standard_frame &block
-
end
-
-
1
def standard_frame slot=true
-
20
with_frame slot do
-
39
wrap_body { yield } if block_given?
-
end
-
end
-
-
1
def with_frame slot=true, header=frame_header, slot_opts={}
-
20
voo.hide :help
-
20
add_name_context
-
20
wrap slot, slot_opts do
-
20
panel do
-
20
[header, frame_help, render_flash, (yield if block_given?)]
-
end
-
end
-
end
-
-
1
def frame_header
-
20
_render_header
-
end
-
-
1
def frame_help
-
20
with_class_up "help-text", "alert alert-info" do
-
20
_render :help
-
end
-
end
-
-
1
def frame_and_form action, form_opts={}
-
8
form_opts ||= {}
-
8
frame do
-
8
card_form action, form_opts do
-
8
yield
-
end
-
end
-
end
-
-
1
def panel
-
20
wrap_with :div, class: classy("d0-card-frame") do
-
20
yield
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/frame.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Header)
-
#
-
1
module Header;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/header.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :header, perms: :none do
-
20
main_header
-
end
-
-
1
def main_header
-
20
header_wrap _render_header_title
-
end
-
-
1
def header_wrap content=nil
-
20
haml :header_wrap, content: (block_given? ? yield : output(content))
-
end
-
-
1
view :header_title, perms: :none do
-
20
header_title_elements
-
end
-
-
1
def header_title_elements
-
20
voo.hide :title_toggle if show_view?(:icon_toggle, :hide)
-
20
title_view = show_view?(:title_toggle, :hide) ? :title_toggle : :title
-
20
[_render_icon_toggle(optional: :hide), _render(title_view)]
-
end
-
-
1
def show_draft_link?
-
card.drafts.present? && @slot_view == :edit
-
end
-
-
1
view :title_toggle, perms: :none do
-
5
content_toggle(_render_title(hide: :title_link))
-
end
-
-
1
view :icon_toggle, perms: :none do
-
direction = @toggle_mode == :close ? :expand : :collapse_down
-
content_toggle icon_tag(direction)
-
end
-
-
1
view :toggle, :icon_toggle # deprecated; use icon_toggle
-
-
1
def content_toggle text=""
-
5
return if text.nil?
-
-
5
verb, adjective = toggle_verb_adjective
-
5
link_to_view adjective, text, title: "#{verb} #{card.name}", # LOCALIZE
-
class: "toggle-#{adjective} toggler nodblclick"
-
end
-
-
1
def toggle_view
-
20
toggle_verb_adjective.last
-
end
-
-
1
TOGGLE_MAP = { close: %w[open open], open: %w[close closed] } # LOCALIZE first item
-
-
1
def toggle_verb_adjective
-
25
TOGGLE_MAP[@toggle_mode || :open] ||
-
raise(Card::Error, "invalid toggle mode: #{@toggle_mode}")
-
end
-
-
1
def structure_editable?
-
card.structure && card.template.ok?(:update)
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/header.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class All; module RichHtml;; module HtmlViews;
-
# Set: All cards (RichHtml, HtmlViews, Guide)
-
#
-
1
module Guide;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/guide.rb"; end
-
1
def guide_card
-
20
guide_card = rule_card(:guide)
-
20
return unless guide_card
-
-
20
guide_card = guide_card.first_card if guide_card.type_id == Card::PointerID
-
20
guide_card if guide_card.ok?(:read)
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :guide, unknown: true, cache: :never, wrap: :slot do
-
guide
-
end
-
-
1
def guide
-
10
guide_text = rule_based_guide
-
10
return "" unless guide_text.present?
-
-
10
if (rule_card = card.help_rule_card)
-
edit_link = with_nest_mode(:normal) { nest(rule_card, view: :edit_link) }
-
guide_text = "<span class='d-none'>#{edit_link}</span>#{guide_text}"
-
end
-
10
wrap_with :div, guide_text, class: classy("guide-text")
-
end
-
-
1
def alert_guide
-
8
guide_text = guide
-
8
return "" unless guide_text.present?
-
-
16
alert(:secondary, true, false, class: "guide") { guide_text }
-
end
-
-
1
def raw_guide_text
-
10
false
-
end
-
-
1
def rule_based_guide
-
10
if raw_guide_text
-
with_nest_mode :normal do
-
process_content raw_guide_text, chunk_list: :references
-
# render guide text with current card's format
-
# so current card's context is used in guide card nests
-
end
-
10
elsif card.guide_card
-
10
with_nest_mode :normal do
-
10
nest card.guide_card, view: :core
-
end
-
else
-
""
-
end
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/guide.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class All; module RichHtml;; module HtmlViews;
-
# Set: All cards (RichHtml, HtmlViews, Help)
-
#
-
1
module Help;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/help.rb"; end
-
1
def help_rule_card
-
30
help_card = rule_card(:help)
-
30
help_card if help_card&.ok?(:read)
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :help, unknown: true, cache: :never, wrap: :slot do
-
8
help = help_text
-
8
return "" unless help.present?
-
-
wrap_with :div, wrap_help_text(help), class: classy("help-text")
-
end
-
-
1
view :help_text, unknown: true, cache: :never do
-
6
wrap_help_text help_text
-
end
-
-
1
def wrap_help_text text
-
6
help = text
-
6
if (rule_card = card.help_rule_card)
-
edit_link = with_nest_mode(:normal) { nest(rule_card, view: :edit_link) }
-
help = "<span class='d-none'>#{edit_link}</span>#{text}"
-
end
-
6
help
-
end
-
-
1
view :lead do
-
class_up "card-slot", "lead"
-
_view_content
-
end
-
-
1
def help_text
-
14
voo.help || rule_based_help
-
end
-
-
1
def raw_help_text
-
14
card.try(:raw_help_text) || card.help_rule_card&.content
-
end
-
-
1
def rule_based_help
-
14
return "" unless (help_text = raw_help_text)
-
-
with_nest_mode :normal do
-
process_content help_text, chunk_list: :references
-
# render help card with current card's format
-
# so current card's context is used in help card nests
-
end
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/help.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class All; module RichHtml;; module HtmlViews;
-
# Set: All cards (RichHtml, HtmlViews, Info)
-
#
-
1
module Info;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/info.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :type, unknown: true do
-
5
link_to_card card.type_card, nil, class: "cardtype"
-
end
-
-
1
view :change do
-
voo.show :title_link
-
voo.hide :menu
-
wrap do
-
[_render_title,
-
_render_menu,
-
_render_last_action]
-
end
-
end
-
-
1
view :last_action do
-
act = card.last_act
-
return unless act
-
-
action = act.action_on card.id
-
return unless action
-
-
action_verb =
-
case action.action_type
-
when :create then "added"
-
when :delete then "deleted"
-
else
-
link_to_view :history, "edited", class: "last-edited", rel: "nofollow"
-
end
-
-
%(
-
<span class="last-update">
-
#{action_verb} #{_render_acted_at} ago by
-
#{subformat(card.last_actor)._render_link}
-
</span>
-
)
-
end
-
-
1
view :type_info do
-
return unless card.type_code != :basic
-
-
wrap_with :span, class: "type-info float-right" do
-
link_to_card card.type_name, nil, class: "navbar-link"
-
end
-
end
-
-
1
view :view_list do
-
%i[bar box info_bar open closed titled labeled content content_panel].map do |v|
-
wrap_with :p, [content_tag(:h3, v), render(v, show: :menu)]
-
end.flatten.join ""
-
end
-
-
1
view :demo do
-
frame do
-
[
-
view_select,
-
wrap_with(:div, view_demo, class: "demo-slot")
-
]
-
end
-
end
-
-
1
def demo_view
-
Env.params[:demo_view] || :core
-
end
-
-
1
def view_demo
-
wrap(true) do
-
render demo_view
-
end
-
end
-
-
1
def view_select
-
card_form :get, success: { view: :demo } do
-
select_tag :demo_view, options_for_select(all_views, demo_view),
-
class: "_submit-on-select"
-
end
-
end
-
-
1
def all_views
-
Card::Set::Format::AbstractFormat::ViewDefinition.views
-
.slice(*self.class.ancestors)
-
.values.map(&:keys).flatten.uniq
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/info.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class All; module RichHtml;; module HtmlViews;
-
# Set: All cards (RichHtml, HtmlViews, Size)
-
#
-
1
module Size;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/size.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
SIZE_IN_PX = { icon: 16, small: 75, medium: 200, large: 500 }.freeze
-
-
# used to control size of svg
-
1
view :max_size do
-
if voo.size.is_a?(String) && voo.size.match(/^\d+x\d+\$/)
-
max_size(*voo.size.split("x"))
-
else
-
px = SIZE_IN_PX[voo.size&.to_sym] || 200
-
max_size px, px
-
end
-
end
-
-
1
def max_size w, h
-
"max-width: #{w}px; max-height: #{h}px"
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/html_views/size.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Menu)
-
#
-
1
module Menu;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/menu.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :menu, denial: :blank, unknown: true do
-
13
return "" if card.unknown?
-
-
6
wrap_with :div, class: "card-menu #{menu_link_classes}" do
-
6
[render_help_link,
-
menu_link,
-
6
(voo.show?(:bridge_link) ? bridge_link(false) : nil)]
-
end
-
end
-
-
1
def menu_link
-
6
case voo.edit
-
when :inline
-
edit_inline_link
-
when :full
-
edit_in_bridge_link
-
else # :standard
-
6
edit_link
-
end
-
end
-
-
1
def edit_view
-
case voo.edit
-
when :inline
-
:edit_inline
-
when :full
-
:edit
-
else # :standard
-
edit_link
-
end
-
end
-
-
1
view :edit_link, unknown: true, denial: :blank do
-
edit_link edit_link_view
-
end
-
-
1
def edit_link_view
-
:edit
-
end
-
-
1
view :full_page_link do
-
full_page_link
-
end
-
-
1
view :bridge_link, unknown: true do
-
bridge_link
-
end
-
-
1
def bridge_link in_modal=true
-
6
opts = { class: "bridge-link" }
-
6
if in_modal
-
# add_class opts, "close"
-
opts["data-slotter-mode"] = "modal-replace"
-
end
-
6
link_to_view :bridge, material_icon(:more_horiz), opts
-
end
-
-
# no caching because help_text view doesn't cache, and we can't have a
-
# stub in the data-content attribute or it will get html escaped.
-
1
view :help_link, cache: :never, unknown: true do
-
6
help_link render_help_text, help_title
-
end
-
-
1
def help_link text=nil, title=nil
-
6
opts = help_popover_opts text, title
-
6
add_class opts, "_card-menu-popover"
-
6
link_to help_icon, opts
-
end
-
-
1
def help_popover_opts text=nil, title=nil
-
6
text ||= render_help_text
-
6
opts = { "data-placement": :left, class: "help-link" }
-
6
popover_opts text, title, opts
-
end
-
-
1
def help_icon
-
6
material_icon("help")
-
end
-
-
1
def help_title
-
6
"#{name_parts_links} (#{render_type}) #{full_page_link unless card.simple?}"
-
end
-
-
1
def name_parts_links
-
6
card.name.parts.map do |part|
-
6
link_to_card part
-
end.join Card::Name.joint
-
end
-
-
1
def full_page_link
-
link_to_card full_page_card, full_page_icon, class: classy("full-page-link")
-
end
-
-
1
def full_page_card
-
card
-
end
-
-
1
def edit_in_bridge_link opts={}
-
edit_link :bridge, opts
-
end
-
-
1
def edit_link view=:edit, opts={}
-
6
link_to_view view, opts.delete(:link_text) || menu_icon,
-
edit_link_opts(opts.reverse_merge(modal: :lg))
-
end
-
-
# @param modal [Symbol] modal size
-
1
def edit_link_opts modal: nil
-
6
opts = { class: classy("edit-link") }
-
6
if modal
-
6
opts[:"data-slotter-mode"] = "modal"
-
6
opts[:"data-modal-class"] = "modal-#{modal}"
-
end
-
6
opts
-
end
-
-
1
def menu_link_classes
-
6
"nodblclick" + (show_view?(:hover_link) ? " _show-on-hover" : "")
-
end
-
-
1
def menu_icon
-
6
material_icon "edit"
-
end
-
-
1
def full_page_icon
-
icon_tag :open_in_new
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/menu.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Modal)
-
#
-
1
module Modal;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/modal.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
MODAL_SIZE = { small: "sm", medium: nil, large: "lg", full: "full" }.freeze
-
1
MODAL_CLOSE_OPTS = { "data-dismiss": "modal",
-
"data-cy": "close-modal" }.freeze
-
-
1
wrapper :modal do |opts={}|
-
1
haml :modal_dialog, body: interior,
-
classes: modal_dialog_classes(opts),
-
title: normalize_modal_option(:title, opts),
-
menu: normalize_modal_option(:menu, opts),
-
footer: normalize_modal_option(:footer, opts)
-
end
-
-
1
def normalize_modal_option key, opts
-
3
val = opts[key]
-
3
return render("modal_#{key}") unless val
-
1
cast_model_option val
-
end
-
-
1
def cast_model_option val
-
2
case val
-
when Symbol
-
cast_model_option_symbol val
-
when Proc
-
val.call(self)
-
else
-
2
val
-
end
-
end
-
-
1
def cast_model_option_symbol val
-
respond_to?(val) ? send(val) : val
-
end
-
-
1
view :modal, wrap: :modal do
-
""
-
end
-
-
1
def show_in_modal_link link_text, body
-
link_to_view :modal, link_text, "data-modal-body": body, "data-slotter-mode": "modal"
-
end
-
-
1
def modal_close_button link_text="Close", opts={}
-
classes = opts.delete(:class)
-
button_opts = opts.merge(MODAL_CLOSE_OPTS)
-
add_class button_opts, classes if classes
-
button_tag link_text, button_opts
-
end
-
-
1
def modal_submit_button opts={}
-
add_class opts, "submit-button _close-modal"
-
submit_button opts
-
end
-
-
1
view :modal_menu, unknown: true, wrap: :modal_menu do
-
1
[close_modal_window, pop_out_modal_window]
-
end
-
-
1
wrapper :modal_menu, :div, class: "modal-menu ml-auto"
-
-
1
view :modal_title, unknown: true do
-
""
-
end
-
-
1
view :modal_footer, unknown: true do
-
button_tag "Close",
-
class: "btn-xs _close-modal float-right",
-
"data-dismiss" => "modal"
-
end
-
-
1
view :modal_link do
-
modal_link _render_title, size: voo.size
-
end
-
-
1
def modal_link text=nil, opts={}
-
opts = modal_link_opts(opts)
-
opts[:path][:layout] ||= :modal
-
link_to text, opts
-
end
-
-
1
def modal_link_opts opts
-
1
add_class opts, "slotter"
-
1
opts.reverse_merge! path: {},
-
"data-slotter-mode": "modal",
-
"data-modal-class": modal_dialog_classes(opts),
-
remote: true
-
1
opts
-
end
-
-
1
def modal_dialog_classes opts
-
2
classes = [classy("modal-dialog")]
-
2
return classes unless opts.present?
-
-
2
add_modal_size_class classes, opts[:size]
-
2
classes << "modal-dialog-centered" if opts[:vertically_centered]
-
2
classes.join " "
-
end
-
-
1
def add_modal_size_class classes, size
-
2
size = normalize_modal_size_class size
-
2
return if size == :medium || size.blank?
-
-
1
classes << "modal-#{MODAL_SIZE[size]}"
-
end
-
-
1
def normalize_modal_size_class size
-
2
size.in?(MODAL_SIZE.keys) ? size : cast_model_option(size)
-
end
-
-
1
def close_modal_window
-
1
link_to icon_tag(:close), path: "",
-
class: "_close-modal close",
-
"data-dismiss": "modal"
-
end
-
-
1
def pop_out_modal_window
-
1
link_to icon_tag(:new_window), path: {}, class: "pop-out-modal close"
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/modal.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Overlay)
-
#
-
1
module Overlay;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/overlay.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
OVERLAY_CLOSE_OPTS = { class: "_close-overlay btn-sm",
-
"data-dismiss": "overlay",
-
type: "button" }.freeze
-
-
1
wrapper :overlay do |opts|
-
class_up "card-slot", "_overlay d0-card-overlay bg-body"
-
@content_body = true
-
voo.hide! :menu
-
overlay_frame true, overlay_header(opts[:title]), opts[:slot] do
-
interior
-
end
-
end
-
-
1
view :overlay_header, unknown: true do
-
overlay_header
-
end
-
-
1
view :overlay_title do
-
_render_title
-
end
-
-
1
view :overlay_menu do
-
wrap_with :div, class: "btn-group btn-group-sm align-self-start ml-auto" do
-
[render_overlay_help_link, slotify_overlay_link, close_overlay_link]
-
end
-
end
-
-
1
view :overlay_help_link, cache: :never, unknown: true do
-
opts = help_popover_opts
-
add_open_guide_opts opts
-
overlay_menu_link "question-circle", opts
-
end
-
-
1
def add_open_guide_opts opts
-
return unless card.guide_card
-
-
slot_selector = ".bridge-sidebar > ._overlay-container-placeholder > .card-slot"
-
opts.merge! remote: true,
-
href: path(mark: card, view: :overlay_guide),
-
"data-slot-selector": slot_selector,
-
"data-slotter-mode": "overlay"
-
add_class opts, "slotter"
-
end
-
-
1
def slotify_overlay_link
-
overlay_menu_link "external-link-square", card: card
-
end
-
-
1
def close_overlay_link
-
overlay_menu_link :close, path: "#", "data-dismiss": "overlay"
-
end
-
-
1
def overlay_close_button link_text="Close", opts={}
-
classes = opts.delete(:class)
-
button_opts = opts.merge(OVERLAY_CLOSE_OPTS)
-
add_class button_opts, classes if classes
-
button_tag link_text, button_opts
-
end
-
-
1
def overlay_delete_button
-
opts = { no_success: true }.merge OVERLAY_CLOSE_OPTS
-
delete_button opts
-
end
-
-
1
def overlay_save_and_close_button
-
submit_button text: "Save and Close", class: "_close-on-success",
-
"data-cy": "submit-overlay"
-
end
-
-
1
def overlay_menu_link icon, args={}
-
add_class args, "border-light text-dark p-1 ml-1"
-
button_link fa_icon(icon, class: "fa-lg"), args.merge(btn_type: "outline-secondary")
-
end
-
-
1
def overlay_header title=nil
-
title ||= _render_overlay_title
-
class_up "d0-card-header", "bg-body"
-
class_up "d0-card-header-title", "d-flex"
-
header_wrap [title, _render_overlay_menu]
-
end
-
-
1
def overlay_frame slot=true, header=render_overlay_header, slot_opts=nil
-
slot_opts ||= {}
-
overlay_framer slot, header, slot_opts do
-
wrap_body { yield }
-
end
-
end
-
-
1
def haml_overlay_frame slot=true, header=render_overlay_header
-
overlay_framer slot, header, {} do
-
haml_wrap_body { yield }
-
end
-
end
-
-
1
private
-
-
1
def overlay_framer slot, header, slot_opts
-
class_up "card-slot", "_overlay"
-
with_frame slot, header, slot_opts do
-
yield
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/overlay.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, ProcessLayout)
-
#
-
1
module ProcessLayout;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/process_layout.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# TODO: use CodeFile cards for these
-
# builtin layouts allow for rescue / testing
-
# HTML_LAYOUTS = Mod::Loader.load_layouts(:html).merge "none" => "{{_main}}"
-
# HAML_LAYOUTS = Mod::Loader.load_layouts(:haml)
-
-
1
def show_with_page_layout view, args
-
23
main!
-
23
args = main_render_args view, args
-
23
if explicit_modal_wrapper?(view) && page_layout.to_sym != :modal
-
render_outside_of_layout view, args
-
else
-
23
render_with_layout view, page_layout, args
-
end
-
end
-
-
1
def main_render_args view, args
-
23
args[:view] = view if view
-
23
args[:main] = true
-
23
args[:main_view] = true
-
23
args
-
end
-
-
1
def page_layout
-
23
params[:layout] || layout_name_from_rule || :default
-
end
-
-
1
def render_with_layout view, layout, args={}
-
23
view_opts = Layout.main_nest_opts(layout, self)
-
23
view ||= view_opts.delete(:view) || default_nest_view
-
23
view_opts[:home_view] = view
-
23
view_opts[:layout] = layout
-
23
render! view, view_opts.reverse_merge(args)
-
end
-
-
1
def render_outside_of_layout view, args
-
body = render_with_layout(nil, page_layout, {})
-
modal = render!(view, args)
-
if body.include?("</body>")
-
# a bit hacky
-
# the problem is that the body tag has to be in the layout
-
# so that you can add layout css classes like <body class="right-sidebar">
-
body.sub!("</body>", "#{modal}</body>")
-
else
-
body += modal
-
end
-
body
-
end
-
-
1
def show_layout?
-
276
!Env.ajax? || params[:layout]
-
end
-
-
1
def explicit_modal_wrapper? view
-
23
return unless view_setting(:wrap, view)
-
-
wrapper_names(view_setting(:wrap, view)).any? { |n| n == :modal || n == :bridge }
-
end
-
-
1
def wrapper_names wrappers
-
case wrappers
-
when Hash then wrappers.keys
-
when Array then wrappers.map { |w| w.is_a?(Array) ? w.first : w }
-
else [wrappers]
-
end
-
end
-
-
1
def layout_name_from_rule
-
23
card.rule_card(:layout)&.try :item_name
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/process_layout.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Show)
-
#
-
1
module Show;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/show.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def show view, args
-
28
content = send show_method, view, args
-
28
show_full_page? ? wrap_with_html_page(content) : content
-
-
# TODO: remove the following after tracking down wikirate encoding bug
-
rescue Card::Error::ServerError => e
-
if e.message.match?(/invalid byte sequence/)
-
Card::Lexicon.cache.reset
-
Rails.logger.info "reset name cache to prevent encoding freakiness"
-
end
-
raise e
-
end
-
-
1
def show_method
-
28
"show_#{show_layout? ? :with : :without}_page_layout"
-
end
-
-
1
def show_without_page_layout view, args
-
5
@main = true if params[:is_main] || args[:main]
-
5
args.delete(:layout)
-
5
view ||= args[:home_view] || :open # default_nest_view
-
5
render! view, args
-
end
-
-
1
def show_full_page?
-
28
!Env.ajax?
-
end
-
-
1
wrapper :html_page do
-
23
<<-HTML.strip_heredoc
-
<!DOCTYPE HTML>
-
<html class="h-100">
-
<head>
-
#{head_content}
-
</head>
-
#{interior}
-
</html>
-
HTML
-
end
-
-
1
def head_content
-
23
nest card.rule_card(:head), view: :head_content
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/show.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Title)
-
#
-
1
module Title;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/title.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :title, compact: true, perms: :none do
-
standard_title
-
end
-
-
1
def standard_title
-
155
name_variant title_in_context(voo.title)
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :title do
-
155
show_view?(:title_link, :hide) ? render_title_link : render_title_no_link
-
end
-
-
1
view :title_link, compact: true, perms: :none do
-
link_to_card card.name, render_title_no_link
-
end
-
-
1
view :title_no_link, compact: true, perms: :none do
-
155
wrapped_title standard_title
-
end
-
-
1
def title_with_link link_text
-
link_to_card card.name, link_text
-
end
-
-
1
def safe_name
-
23
h super
-
end
-
-
1
def title_in_context title=nil
-
155
title = title&.html_safe
-
# escape titles generated from card names, but not those set explicitly
-
155
h super(title)
-
end
-
-
1
def wrapped_title title
-
155
wrap_with :span, class: classy("card-title"), title: title do
-
155
title.to_name.parts.join wrapped_joint
-
end
-
end
-
-
1
def wrapped_joint
-
155
wrap_with :span, "+", classy("joint")
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/title.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module RichHtml;
-
# Set: All cards (RichHtml, Wrapper)
-
#
-
1
module Wrapper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/wrapper.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# Does two main things:
-
# (1) gives CSS classes for styling and
-
# (2) adds card data for javascript - including the "card-slot" class,
-
# which in principle is not supposed to be in styles
-
1
def wrap slot=true, slot_attr={}, tag=:div, &block
-
74
method_wrap :wrap_with, tag, slot, slot_attr, &block
-
end
-
-
1
wrapper :slot do |opts|
-
20
class_up "card-slot", opts[:class] if opts[:class]
-
20
method_wrap :wrap_with, :div, true, opts do
-
20
interior
-
end
-
end
-
-
1
def haml_wrap slot=true, slot_attr={}, tag=:div, &block
-
method_wrap :haml_tag, tag, slot, slot_attr, &block
-
end
-
-
1
def method_wrap method, tag, slot, slot_attr, &block
-
94
@slot_view = @current_view
-
94
debug_slot do
-
94
send method, tag, slot_attributes(slot, slot_attr), &block
-
end
-
end
-
-
1
def slot_attributes slot, slot_attr
-
94
{ id: slot_id, class: wrap_classes(slot), data: wrap_data }.tap do |hash|
-
94
add_class hash, slot_attr.delete(:class)
-
94
hash.deep_merge! slot_attr
-
end
-
end
-
-
1
def slot_id
-
94
"#{card.name.safe_key}-#{@current_view}-view"
-
end
-
-
1
def wrap_data slot=true
-
94
with_slot_data slot do
-
94
{ "card-id": card.id, "card-name": h(card.name),
-
"slot-id": SecureRandom.hex(10) }
-
end
-
end
-
-
1
def with_slot_data slot
-
94
hash = yield
-
# rails helper convert slot hash to json
-
# but haml joins nested keys with a dash
-
94
hash[:slot] = slot_options_json if slot
-
94
hash
-
end
-
-
1
def slot_options_json
-
94
html_escape_except_quotes JSON(slot_options)
-
end
-
-
1
def slot_options
-
94
options = voo ? voo.slot_options : {}
-
94
name_context_slot_option options
-
94
options
-
end
-
-
1
def name_context_slot_option opts
-
94
return unless initial_context_names.present?
-
-
2
opts[:name_context] = initial_context_names.map(&:key) * ","
-
end
-
-
1
def debug_slot
-
94
debug_slot? ? debug_slot_wrap { yield } : yield
-
end
-
-
1
def debug_slot?
-
94
params[:debug] == "slot"
-
end
-
-
1
def debug_slot_wrap
-
pre = "<!--\n\n#{' ' * depth}"
-
post = " SLOT: #{h card.name}\n\n-->"
-
[pre, "BEGIN", post, yield, pre, "END", post].join
-
end
-
-
1
def wrap_classes slot
-
94
list = slot ? ["card-slot"] : []
-
94
list += ["#{@current_view}-view", card.safe_set_keys]
-
94
list << "STRUCTURE-#{voo.structure.to_name.key}" if voo&.structure
-
94
classy list
-
end
-
-
1
def wrap_body
-
38
wrap_with(:div, class: body_css_classes) { yield }
-
end
-
-
1
def haml_wrap_body
-
wrap_body do
-
capture_haml { yield }
-
end
-
end
-
-
1
def body_css_classes
-
19
css_classes = ["d0-card-body"]
-
19
css_classes += ["d0-card-content", card.safe_set_keys] if @content_body
-
19
classy(*css_classes)
-
end
-
-
1
def wrap_main
-
23
return yield if no_main_wrap?
-
-
23
wrap_with :div, yield, id: "main"
-
end
-
-
1
def no_main_wrap?
-
23
Env.ajax? || params[:layout] == "none"
-
end
-
-
1
def wrap_with tag, content_or_args={}, html_args={}
-
1362
content = block_given? ? yield : content_or_args
-
1342
tag_args = block_given? ? content_or_args : html_args
-
2684
content_tag(tag, tag_args) { output(content).to_s.html_safe }
-
end
-
-
1
def wrap_each_with tag, content_or_args={}, args={}
-
content = block_given? ? yield(args) : content_or_args
-
args = block_given? ? content_or_args : args
-
content.compact.map do |item|
-
wrap_with(tag, args) { item }
-
end.join "\n"
-
end
-
-
1
private
-
-
1
def html_escape_except_quotes string
-
# to be used inside single quotes (makes for readable json attributes)
-
94
string.to_s.gsub(/&/, "&")
-
.gsub(/\'/, "'")
-
.gsub(/>/, ">")
-
.gsub(/</, "<")
-
end
-
-
1
wrapper :div, :div
-
1
wrapper :em, :em
-
-
1
wrapper :none do
-
interior
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/all/rich_html/wrapper.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Discussion" cards
-
#
-
1
module Discussion;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/discussion.rb"; end
-
1
view :titled, unknown: true do
-
voo.show :comment_box
-
super()
-
end
-
-
1
view :open, unknown: true do
-
voo.show :comment_box
-
super()
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/discussion.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Head" cards
-
#
-
1
module Head;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/head.rb"; end
-
1
def ok_to_read
-
23
true
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :head_content do
-
23
process_content render_raw
-
end
-
-
1
view :one_line_content do
-
raw_one_line_content
-
end
-
-
1
view :core do
-
process_content ::CodeRay.scan(render_raw, :html).div
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/head.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+TypePlusRight" cards
-
#
-
1
module TypePlusRight;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/type_plus_right.rb"; end
-
1
def related_sets _with_self=false
-
[[name, Card::Set::TypePlusRight.label(name.left)],
-
["#{name[1]}+*right", Card::Set::Right.label(name[1])]]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/type_plus_right.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+WhenCreated" cards
-
#
-
1
module WhenCreated;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/when_created.rb"; end
-
1
def content
-
return "" unless left&.real?
-
I18n.localize left.created_at, format: :card_dayofwk_min_tz
-
end
-
-
# view :core, :raw
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/when_created.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+WhenLastEdited" cards
-
#
-
1
module WhenLastEdited;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/when_last_edited.rb"; end
-
1
def content
-
return "" unless left&.real?
-
I18n.localize left.updated_at, format: :card_dayofwk_min_tz
-
end
-
-
# view :core, :raw
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/right/when_last_edited.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Alerts"
-
#
-
1
module Alerts;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/alerts.rb"; end
-
1
def content
-
"<!-- *alerts is deprecated. please remove from layout -->"
-
end
-
-
# view :core, :raw
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/alerts.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Cardtype"
-
#
-
1
module Cardtype;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/cardtype.rb"; end
-
GROUP = {
-
1
"Text" => %w[RichText PlainText Markdown Phrase HTML],
-
"Data" => %w[Number Toggle Date URI],
-
"Upload" => %w[File Image],
-
"Custom" => [],
-
"Organize" => ["List", "Pointer", "Search", "Link list", "Nest list",
-
"Mirror List", "Mirrored List"],
-
"Template" => ["Notification template", "Email template", "Twitter template"],
-
"Admin" => ["Cardtype", "User", "Role", "Sign up", "Session", "Set", "Setting"],
-
"Styling" => ["Layout", "Skin", "Bootswatch skin", "Customized bootswatch skin", "CSS", "SCSS"],
-
"Scripting" => %w[JSON JavaScript CoffeeScript]
-
}.freeze
-
-
#DEFAULT_RULE_GROUPS = ["Text", "Data", "Upload", "Organize - Search"]
-
#STRUCTURE_RULE_GROUPS = ["Text", "Organize > Search"]
-
-
# group for each cardtype: { "RichText => "Content", "Layout" => "Admin", ... }
-
1
GROUP_MAP = GROUP.each_with_object({}) do |(cat, types), h|
-
46
types.each { |t| h[t] = cat }
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :grouped_list do
-
GROUP.keys.map do |group|
-
type_list = group == "Custom" ? custom_types : GROUP[group]
-
next if type_list.empty?
-
-
[wrap_with(:h5, group), wrap_with(:p, listing(type_list))]
-
end.flatten.join "\n"
-
end
-
-
1
def custom_types
-
custom_types = []
-
-
Card.search(type_id: Card::CardtypeID, return: "name").each do |name|
-
next if ::Card::Set::Self::Cardtype::GROUP_MAP[name]
-
-
custom_types << name
-
end
-
custom_types
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/cardtype.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Codenames"
-
#
-
1
module Codenames;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/codenames.rb"; end
-
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/codenames.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Foot"
-
#
-
1
module Foot;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/foot.rb"; end
-
-
1
def content
-
"<!-- *foot is deprecated. please remove from layout -->"
-
end
-
-
# view :core, :raw
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/foot.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Home"
-
#
-
1
module Home;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/home.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :home_url, perms: :none do
-
card_url ""
-
end
-
-
1
view :home_path, perms: :none do
-
46
card_path ""
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/home.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Now"
-
#
-
1
module Now;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/now.rb"; end
-
-
1
def content
-
I18n.localize(Time.now, format: :card_dayofwk_min_tz)
-
end
-
-
# view :core, :raw
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/now.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Sidebar"
-
#
-
1
module Sidebar;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/sidebar.rb"; end
-
1
def raw_help_text
-
<<-TEXT
-
Sidebar content of [[Layouts]] with sidebar. [[http://decko.org/sidebar|more]]
-
TEXT
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/self/sidebar.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Basic" cards
-
#
-
1
module Basic;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/basic.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :open_content do
-
2
with_table_of_contents _render_core
-
end
-
-
1
view :titled_content do
-
with_table_of_contents _render_core
-
end
-
-
1
def with_table_of_contents content
-
2
table_of_contents(content) || content
-
end
-
-
1
def table_of_contents content
-
2
return if nest_mode == :compact || !content.present?
-
-
1
min = card.rule(:table_of_contents).to_i
-
1
return unless min && min > 0
-
-
toc = toc_items content
-
if toc.flatten.length >= min
-
content.replace(
-
%( <div class="table-of-contents"> <h5>#{tr(:toc)}</h5> ) +
-
make_table_of_contents_list(toc) + "</div>" + content
-
)
-
end
-
end
-
-
1
def toc_items content
-
toc = []
-
dep = 1
-
content.gsub!(/<(h\d)>(.*?)<\/h\d>/i) do |match|
-
if $LAST_MATCH_INFO
-
tag, value = $LAST_MATCH_INFO[1, 2]
-
value = strip_tags(value).strip
-
next if value.empty?
-
item = { value: value, uri: URI.escape(value) }
-
case tag.downcase
-
when "h1"
-
item[:depth] = dep = 1
-
toc << item
-
when "h2"
-
toc << [] if dep == 1
-
item[:depth] = dep = 2
-
toc.last << item
-
end
-
%(<a name="#{item[:uri]}"></a>#{match})
-
end
-
end
-
toc
-
end
-
-
1
def make_table_of_contents_list items
-
list = items.map do |i|
-
if i.is_a?(Array)
-
make_table_of_contents_list(i)
-
else
-
%(<li><a href="##{i[:uri]}"> #{i[:value]}</a></li>)
-
end
-
end.join("\n")
-
"<ol>" + list + "</ol>"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/basic.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Cardtype" cards
-
#
-
1
module Cardtype;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/cardtype.rb"; end
-
1
include_set Abstract::CqlSearch
-
-
1
def cql_content
-
{ type_id: id, sort: :name }
-
end
-
-
1
def related_sets with_self=false
-
sets = []
-
sets << ["#{name}+*type", Card::Set::Type.label(name)] if known?
-
sets + super
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :type, unknown: true do
-
1
link_to_card card.type_card, nil, class: "cardtype"
-
end
-
-
1
def type_formgroup args={}
-
if card.cards_of_type_exist?
-
wrap_with :div, tr(:cards_exist, cardname: safe_name)
-
else
-
super
-
end
-
end
-
-
1
view :add_link do
-
add_link
-
end
-
-
1
view :add_button do
-
1
add_link class: "btn btn-secondary"
-
end
-
-
1
def add_link opts={}
-
1
voo.title ||= tr(:add_card, cardname: safe_name)
-
1
link_to render_title, add_link_opts(opts)
-
end
-
-
1
def add_link_opts opts
-
1
modal = opts.delete :modal
-
1
modal = true if modal.nil?
-
1
opts[:path] = add_path(modal ? :new_in_modal : :new)
-
1
modal ? modal_link_opts(opts) : opts
-
end
-
-
1
view :add_url do
-
card_url _render_add_path
-
end
-
-
1
def add_path view
-
1
path_args = { mark: card.name }
-
1
process_voo_params(path_args) if voo.params
-
1
if view == :new
-
path_args[:action] = :new
-
else
-
1
path_args[:action] = :type
-
1
path_args[:view] = view
-
end
-
1
path path_args
-
end
-
-
# don't cache because it depends on update permission for another card
-
1
view :configure_link, cache: :never, perms: ->(fmt) { fmt.can_configure? } do
-
configure_link
-
end
-
-
1
def can_configure?
-
1
Card.fetch(card, :type, :structure, new: {}).ok? :update
-
end
-
-
1
view :configure_button, cache: :never, denial: :blank,
-
1
perms: ->(fmt) { fmt.can_configure? } do
-
1
configure_link "btn btn-secondary"
-
end
-
-
1
def configure_link css_class=nil
-
1
return "" unless Card.fetch(card, :type, :structure, new: {}).ok? :update
-
-
1
voo.title ||= tr(:configure_card, cardname: safe_name.pluralize)
-
1
title = _render_title
-
1
link_to_card card, title, path: { view: :bridge, bridge: { tab: :rules_tab },
-
set: Card::Name[safe_name, :type] },
-
class: css_classes("configure-type-link ml-3", css_class)
-
end
-
-
1
private
-
-
1
def process_voo_params path_args
-
context = ((@parent&.card) || card).name
-
Rack::Utils.parse_nested_query(voo.params).each do |key, value|
-
value = value.to_name.absolute(context) if value
-
key = key.to_name.absolute(context)
-
path_args[key] = value
-
end
-
end
-
end
-
-
1
include Basic
-
-
1
def cards_of_type_exist?
-
!new_card? && Card.where(trash: false, type_id: id).exists?
-
end
-
-
1
def create_ok?
-
Card.new(type_id: id).ok? :create
-
end
-
-
1
def was_cardtype?
-
3
type_id_before_act == Card::CardtypeID
-
end
-
-
1
event :check_for_cards_of_type, after: :validate_delete do
-
errors.add :cardtype, tr(:cards_exist, cardname: name) if cards_of_type_exist?
-
end
-
-
1
event :check_for_cards_of_type_when_type_changed,
-
:validate, changing: :type, when: :was_cardtype? do
-
if cards_of_type_exist?
-
errors.add :cardtype, tr(:error_cant_alter, name: name_before_act)
-
end
-
end
-
-
1
event :validate_cardtype_name, :validate, on: :save, changed: :name do
-
4
if %r{[<>/]}.match?(name)
-
errors.add :name, tr(:error_invalid_character_in_cardtype, banned: "<, >, /")
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/cardtype.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "LayoutType" cards
-
#
-
# -*- encoding : utf-8 -*-
-
1
module LayoutType;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/layout_type.rb"; end
-
-
1
include_set Type::Html
-
-
1
event :update_layout_registry, :finalize, on: :update do
-
Card::Layout.deregister_layout name
-
Card::Layout.register_layout_with_nest name, format
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
with_nest_mode :template do
-
process_content ::CodeRay.scan(_render_raw, :html).div
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/layout_type.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "NotificationTemplate" cards
-
#
-
1
module NotificationTemplate;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/notification_template.rb"; end
-
1
card_reader :contextual_class
-
1
card_reader :disappear
-
1
card_reader :message
-
-
1
def deliver context
-
success.flash alert_message(context)
-
end
-
-
1
def alert_message context
-
mcard = message.present? ? message_card : self
-
format(:html).alert_message context, mcard
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def alert_message context, message_card
-
mformat = subformat message_card
-
alert card.alert_class, true, card.disappear? do
-
mformat.contextual_content context, view: alert_view(mformat)
-
end
-
end
-
-
1
def alert_view format
-
format.respond_to?(:notify) ? format.notify : :core
-
end
-
end
-
-
1
def disappear?
-
disappear.present? ? disappear_card.checked? : true
-
end
-
-
1
def alert_class
-
contextual_class.present? ? contextual_class_card.item_name : :success
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/notification_template.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Number" cards
-
#
-
1
module Number;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/number.rb"; end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:text_field
-
end
-
end
-
-
1
event :validate_number, :validate, on: :save do
-
errors.add :content, tr(:not_numeric, content: content) unless valid_number?(content)
-
end
-
-
1
def valid_number? string
-
return true if string.empty?
-
-
valid = true
-
begin
-
Kernel.Float(string)
-
rescue ArgumentError, TypeError
-
valid = false
-
end
-
valid
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/number.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Phrase" cards
-
#
-
1
module Phrase;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/phrase.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:text_field
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/phrase.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Session" cards
-
#
-
1
module Session;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/session.rb"; end
-
1
include_set Pointer
-
-
1
def virtual?
-
74
session_content.present?
-
end
-
-
1
def history?
-
false
-
end
-
-
1
def followable?
-
false
-
end
-
-
1
def recaptcha_on?
-
24
false
-
end
-
-
1
def session_key
-
91
"_card_#{key}"
-
end
-
-
1
def session_content
-
91
Env.session[session_key]
-
end
-
-
1
def session_content= val
-
Env.session[session_key] = val
-
end
-
-
1
def content
-
45
db_content || session_content
-
end
-
-
1
event :store_in_session, :prepare_to_store, on: :save do
-
self.session_content = db_content
-
abort :success
-
end
-
-
1
event :delete_in_session, :prepare_to_store, on: :delete do
-
self.session_content = nil
-
abort :success
-
end
-
-
1
def ok_to_create
-
true
-
end
-
-
1
def ok_to_update
-
true
-
end
-
-
1
def add_to_trash args
-
yield args.merge trash: true
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
before :core do
-
voo.items[:view] = :name
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/session.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Toggle" cards
-
#
-
1
module Toggle;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/toggle.rb"; end
-
1
def checked?
-
content == "1"
-
end
-
-
1
view :core do
-
case card.content.to_i
-
when 1 then tr(:yes)
-
when 0 then tr(:no)
-
else
-
"?"
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :input do
-
toggle
-
end
-
-
1
view :labeled_editor do
-
toggle + toggle_label
-
end
-
-
1
def toggle
-
check_box :content
-
end
-
-
1
def toggle_label
-
label :content, card.name.tag
-
end
-
-
1
def one_line_content
-
short_content
-
end
-
-
1
def short_content
-
render_core
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/toggle.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Uri" cards
-
#
-
1
module Uri;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/uri.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
link_to_resource _render_raw, render_title
-
end
-
-
1
view :url_link do
-
link_to_resource _render_raw
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
:text_field
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/standard/set/type/uri.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (EmailField)
-
#
-
1
module EmailField;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/abstract/email_field.rb"; end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
# turn off autodetection of uri's
-
1
def chunk_list
-
:references
-
end
-
end
-
-
# format :html do
-
# def pointer_items args
-
# card.item_names(context: :raw).map do |iname|
-
# wrap_item iname, args
-
# end
-
# end
-
# end#
-
-
2
module EmailTextFormat; module_parent.send :register_set_format, Card::Format::EmailTextFormat, self; extend Card::Set::AbstractFormat
-
1
def email_addresses context
-
2
context ||= self
-
2
card.item_names(context: context.name).map do |name|
-
# FIXME: context is processed twice here because pointers absolutize
-
# item_names by default while other types can return relative names.
-
# That's poor default behavior and should be fixed!
-
2
name = name.to_name.absolute context
-
2
email_address?(name) ? name : email_address_from_card(name, context)
-
end.flatten.compact.join(", ")
-
end
-
-
1
def email_address? string
-
2
string =~ /.+\@.+\..+/
-
end
-
-
1
def email_address_from_card name, context
-
2
card = Card.fetch name
-
2
card.account&.email || email_addresses_from_card_content(card, context)
-
end
-
-
1
def email_addresses_from_card_content card, context
-
subformat(card).contextual_content(context).split(/[,\n]/)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/abstract/email_field.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (TestContext)
-
#
-
1
module TestContext;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/abstract/test_context.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
2
return super() if voo.hide? :test_context
-
card.with_context test_context_card do
-
super()
-
end
-
end
-
-
1
def test_context_card
-
card.left.fetch(:test_context)&.item_card
-
end
-
end
-
-
2
module EmailHtmlFormat; module_parent.send :register_set_format, Card::Format::EmailHtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
2
voo.hide! :test_context
-
2
super()
-
end
-
end
-
-
2
module EmailTextFormat; module_parent.send :register_set_format, Card::Format::EmailTextFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
4
voo.hide! :test_context
-
4
super()
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/abstract/test_context.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EmailHtml)
-
#
-
1
module EmailHtml;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/all/email_html.rb"; end
-
2
module EmailHtmlFormat; module_parent.send :register_set_format, Card::Format::EmailHtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :unknown do
-
""
-
end
-
-
1
view :compact_missing do
-
""
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/all/email_html.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EmailText)
-
#
-
1
module EmailText;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/all/email_text.rb"; end
-
-
2
module EmailTextFormat; module_parent.send :register_set_format, Card::Format::EmailTextFormat, self; extend Card::Set::AbstractFormat
-
1
view :unknown do
-
""
-
end
-
-
1
view :compact_missing do
-
""
-
end
-
-
1
view :last_action, perms: :none, cache: :never do
-
_render_last_action_verb
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/all/email_text.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Bcc" cards
-
#
-
1
module Bcc;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/right/bcc.rb"; end
-
1
include_set Abstract::EmailField
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/right/bcc.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Cc" cards
-
#
-
1
module Cc;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/right/cc.rb"; end
-
1
include_set Abstract::EmailField
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/right/cc.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+From" cards
-
#
-
1
module From;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/right/from.rb"; end
-
1
include_set Abstract::EmailField
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/right/from.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+HtmlMessage" cards
-
#
-
1
module HtmlMessage;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/right/html_message.rb"; end
-
1
include_set Abstract::TestContext
-
-
1
def clean_html?
-
false
-
end
-
-
2
module EmailHtmlFormat; module_parent.send :register_set_format, Card::Format::EmailHtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def email_content context
-
2
content = contextual_content context
-
2
return unless content.present?
-
2
Card::Mailer.layout content
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/right/html_message.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Subject" cards
-
#
-
1
module Subject;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/right/subject.rb"; end
-
1
include_set Abstract::TestContext
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/right/subject.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+TextMessage" cards
-
#
-
1
module TextMessage;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/right/text_message.rb"; end
-
1
include_set Abstract::TestContext
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/right/text_message.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+To" cards
-
#
-
1
module To;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/right/to.rb"; end
-
1
include_set Abstract::EmailField
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/right/to.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "EmailTemplate" cards
-
#
-
1
module EmailTemplate;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/type/email_template.rb"; end
-
-
1
def clean_html?
-
false
-
end
-
-
1
def deliver context=nil, fields={}, opts={}
-
mail = format.mail context, fields, opts
-
mail.deliver
-
rescue Net::SMTPError => exception
-
errors.add :exception, exception.message
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def mail context=nil, fields={}, opts={}
-
2
config = card.email_config context, fields, opts
-
2
fmt = self # self is <Mail::Message> within the new_mail block
-
2
Card::Mailer.new_mail config do
-
2
fmt.message_body self, config
-
2
fmt.add_attachments self, config.delete(:attach)
-
end
-
end
-
-
1
def message_body mail, config
-
2
config[:html_message] &&= config[:html_message].call mail
-
2
method, args = body_method_and_args config[:html_message].present?,
-
config[:text_message].present?
-
8
args = Array.wrap(args).map { |arg| config[arg] }
-
2
send method, mail, *args
-
end
-
-
1
def body_method_and_args html, text
-
2
if html && text
-
2
[:text_and_html_message, %i[text_message html_message attach]]
-
elsif html
-
%i[html_body html_message]
-
else
-
%i[text_body text_message]
-
end
-
end
-
-
1
def text_and_html_message mail, text_message, html_message, attachment_list=nil
-
2
fmt = self
-
2
if attachment_list&.any?
-
mail.multipart_mixed text_message, html_message
-
else
-
4
mail.text_part { body text_message }
-
4
mail.html_part { fmt.html_body self, html_message }
-
end
-
end
-
-
1
def multipart_mixed mail, text_message, html_message
-
mail.content_type "multipart/mixed"
-
mail.part content_type: "multipart/alternative" do |copy|
-
copy.part content_type: "text/plain" do |plain|
-
plain.body = text_message
-
end
-
copy.part content_type: "text/html" do |html|
-
html.body = html_message
-
end
-
end
-
end
-
-
1
def html_body mail, message
-
2
mail.content_type "text/html; charset=UTF-8"
-
2
mail.body message
-
end
-
-
1
def text_body mail, message
-
mail.content_type "text/plain; charset=UTF-8"
-
mail.text_part { body message }
-
end
-
-
1
def add_attachments mail, list
-
2
return unless list.present?
-
each_valid_attachment list do |file, index|
-
mail.add_file filename: attachment_name(file, index),
-
content: File.read(file.path)
-
end
-
end
-
-
1
def each_valid_attachment list
-
list.each_with_index do |cardname, index|
-
next unless (file = Card[cardname]&.try(:attachment))
-
yield file, index
-
end
-
end
-
-
1
def attachment_name file, number
-
"attachment-#{number + 1}.#{file.extension}"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/type/email_template.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Type; module EmailTemplate;
-
# Set: All "EmailTemplate+EmailConfig" cards (EmailConfig)
-
#
-
1
module EmailConfig;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-email/set/type/email_template/email_config.rb"; end
-
EMAIL_FIELDS =
-
1
%i[to from cc bcc attach subject text_message html_message].freeze
-
-
EMAIL_FIELD_METHODS =
-
1
{ subject: :contextual_content,
-
text_message: :contextual_content,
-
attach: :extended_item_contents }.freeze
-
-
# @param [Card] context the card in whose context all email fields will be interpreted
-
# @param [Hash] fields override any templated field configurations with hash values
-
# @param [Hash] opts options for rendering. unknown options become format options
-
# @option opts [Card, String, Integer] :auth user identifier. render as this user
-
1
def email_config context, fields={}, opts={}
-
2
@active_email_context = context || self
-
2
auth = opts.delete :auth
-
2
config = EMAIL_FIELDS.each_with_object({}) do |field, conf|
-
16
conf[field] = fields[field] || email_field_from_card(field, auth, opts)
-
end
-
2
safe_from_and_reply_to! config
-
20
config.select { |_k, v| v.present? }
-
end
-
-
1
def email_field_from_card field, auth, format_opts
-
14
return unless (field_card = fetch(field))
-
8
auth ||= field_card.updater
-
8
special_email_field_method(field, field_card, auth, format_opts) ||
-
standard_email_field(field, field_card, auth, format_opts)
-
end
-
-
1
def special_email_field_method field, field_card, auth, format_opts
-
8
method = "email_#{field}_field"
-
8
return unless respond_to? method
-
2
send method, field_card, auth, format_opts
-
end
-
-
1
def standard_email_field field, field_card, auth, format_opts
-
6
method = EMAIL_FIELD_METHODS[field] || :email_addresses
-
6
format_opts = format_opts.merge format: :email_text
-
6
Auth.as auth do
-
6
field_card.format(format_opts).send method, @active_email_context
-
end
-
end
-
-
# html messages return procs because image attachments can't be properly rendered
-
# without a mail object. (which isn't available at initial config time)
-
1
def email_html_message_field message_card, auth, format_opts
-
2
proc do |mail|
-
2
Auth.as auth do
-
2
format_opts = format_opts.merge format: :email_html, active_mail: mail
-
2
message_card.format(format_opts).email_content @active_email_context
-
end
-
end
-
end
-
-
# whenever a default "from" field is configured in Card::Mailer, emails are always
-
# actually "from" that address
-
1
def safe_from_and_reply_to! config
-
2
conf_name, conf_email = configured_from_name_and_email config[:from]
-
2
actual_email = Card::Mailer.default[:from] || conf_email
-
2
config[:from] = email_from_field_value conf_name, conf_email, actual_email
-
2
config[:reply_to] ||= actual_email
-
end
-
-
1
def email_from_field_value conf_name, conf_email, actual_email
-
2
conf_text = conf_name || conf_email
-
2
if conf_text != actual_email
-
%("#{conf_text}" <#{actual_email}>)
-
2
elsif actual_email.present?
-
2
actual_email
-
else
-
Card[WagnBotID].account.email
-
end
-
end
-
-
1
def configured_from_name_and_email raw_string
-
2
if raw_string =~ /(.*)\<(.*)>/
-
[Regexp.last_match(1).strip, Regexp.last_match(2)]
-
else
-
2
[nil, raw_string]
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-email/set/type/email_template/email_config.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (AccountField)
-
#
-
1
module AccountField;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/abstract/account_field.rb"; end
-
-
# allow account owner to update account field content
-
1
def ok_to_update
-
return true if own_account? && !name_changed? && !type_id_changed?
-
-
super
-
end
-
-
# force inherit permission on create
-
# (cannot be done with rule, because sets are not addressable)
-
1
def permission_rule_id action
-
if action == :create
-
left_permission_rule_id action
-
else
-
super
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/abstract/account_field.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Accountable)
-
#
-
1
module Accountable;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/abstract/accountable.rb"; end
-
1
def account
-
fetch :account, new: {}
-
end
-
-
1
def default_account_status
-
"active"
-
end
-
-
1
def current_account?
-
id && Auth.current_id == id
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def default_bridge_tab
-
card.current_account? ? :account_tab : super
-
end
-
-
1
view :account_tab do
-
bridge_pill_sections "Account" do
-
[["Settings", account_details_items],
-
["Content", account_content_items]]
-
end
-
end
-
-
1
def show_account_tab?
-
card.account.real?
-
end
-
-
1
def account_formgroups
-
Auth.as_bot do
-
subformat(card.account)._render :content_formgroups, structure: true
-
end
-
end
-
-
1
def account_details_items
-
[
-
["Email and Password", :account,
-
{ path: { slot: { hide: %i[help_link bridge_link] } } }],
-
["Roles", :roles,
-
{ path: { view: :content_with_edit_button } }],
-
["Notifications", :follow]
-
]
-
end
-
-
1
def account_content_items
-
[["Created", :created],
-
["Edited", :edited]]
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/abstract/accountable.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Account)
-
#
-
1
module Account;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/all/account.rb"; end
-
1
module ClassMethods
-
1
def default_accounted_type_id
-
UserID
-
end
-
end
-
-
1
def account
-
80
fetch :account
-
end
-
-
1
def parties
-
1322
@parties ||= (all_enabled_roles << id).flatten.reject(&:blank?)
-
end
-
-
1
def among? ok_ids
-
1296
ok_ids.any? do |ok_id|
-
1296
ok_id == AnyoneID ||
-
1251
(ok_id == AnyoneWithRoleID && all_enabled_roles.size > 1) ||
-
parties.member?(ok_id)
-
end
-
end
-
-
1
def own_account?
-
# card is +*account card of signed_in user.
-
name.part_names[0].key == Auth.as_card.key &&
-
name.part_names[1].key == Card[:account].key
-
end
-
-
1
def read_rules
-
134
@read_rules ||= fetch_read_rules
-
end
-
-
1
def read_rules_hash
-
778
@read_rules_hash ||= read_rules.each_with_object({}) { |id, h| h[id] = true }
-
end
-
-
1
def fetch_read_rules
-
71
return [] if id == WagnBotID # always_ok, so not needed
-
-
71
([AnyoneID] + parties).each_with_object([]) do |party_id, rule_ids|
-
251
next unless (cache = Card::Rule.read_rule_cache[party_id])
-
71
rule_ids.concat cache
-
end
-
end
-
-
1
def clear_roles
-
@parties = @all_roles = @all_active_roles = @read_rules = nil
-
end
-
-
1
def with_clear_roles
-
a, b, c, d = @parties, @all_roles, @all_active_roles, @read_rules
-
yield
-
ensure
-
@parties, @all_roles, @all_active_roles, @read_rules = a, b, c, d
-
end
-
-
1
def all_enabled_roles
-
165
@all_active_roles ||= (id == AnonymousID ? [] : enabled_role_ids)
-
end
-
-
1
def all_roles
-
@all_roles ||= (id == AnonymousID ? [] : fetch_roles)
-
end
-
-
1
def enabled_role_ids
-
74
Auth.as_bot do
-
# workaround for broken migrations
-
74
return fetch_roles unless Card::Codename.exists? :enabled_roles
-
-
74
enabled = enabled_roles_card
-
74
enabled.virtual? ? enabled.item_ids : fetch_roles
-
end
-
end
-
-
1
def enabled_roles_card
-
74
fetch :enabled_roles, eager_cache: true, new: { type_id: SessionID }
-
end
-
-
1
def fetch_roles
-
74
[AnyoneSignedInID] + role_ids_from_roles_trait
-
end
-
-
1
def role_ids_from_roles_trait
-
74
Auth.as_bot do
-
74
role_trait = fetch :roles
-
74
role_trait ? role_trait.item_ids : []
-
end
-
end
-
-
1
event :generate_token do
-
Digest::SHA1.hexdigest "--#{Time.zone.now.to_f}--#{rand 10}--"
-
end
-
-
1
event :set_stamper, :prepare_to_validate do
-
332
self.updater_id = Auth.current_id
-
332
self.creator_id = updater_id if new_card?
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/all/account.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Account" cards
-
#
-
# -*- encoding : utf-8 -*-
-
1
module Account;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/account.rb"; end
-
-
1
card_accessor :email
-
1
card_accessor :password
-
1
card_accessor :salt
-
1
card_accessor :status
-
1
card_accessor :api_key
-
-
1
require_field :email
-
-
1
def accounted
-
left
-
end
-
-
1
def accounted_id
-
left_id
-
end
-
-
1
def ok_to_read
-
own_account? ? true : super
-
end
-
-
# allow account owner to update account field content
-
1
def ok_to_update
-
return true if own_account? && !name_changed? && !type_id_changed?
-
-
super
-
end
-
-
1
def changes_visible? act
-
act.actions_affecting(act.card).each do |action|
-
return true if action.card.ok? :read
-
end
-
false
-
end
-
-
1
def send_account_email email_template
-
ecard = Card[email_template]
-
unless ecard&.type_id == EmailTemplateID
-
raise Card::Error, "invalid email template: #{email_template}"
-
end
-
-
ecard.deliver self, to: email
-
end
-
-
1
def validate_api_key! api_key
-
api_key_card.validate! api_key
-
end
-
-
1
def method_missing method, *args
-
super unless args.empty? && (matches = method.match(/^(?<status>.*)\?$/))
-
-
status == matches[:status]
-
end
-
-
1
def respond_to_missing? method, _include_private=false
-
method.match?(/\?/) ? true : super
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/account.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Right; module Account;
-
# Set: All "+Account+Events" cards (Events)
-
#
-
#### ON CREATE
-
1
module Events;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/account/events.rb"; end
-
-
1
event :set_default_salt, :prepare_to_validate, on: :create do
-
add_subfield(:salt).generate
-
end
-
-
1
event :set_default_status, :prepare_to_validate, on: :create do
-
add_subfield :status, content: (accounted&.try(:default_account_status) || "active")
-
end
-
-
# ON UPDATE
-
-
# reset password emails contain a link to update the +*account card
-
# and trigger this event
-
1
event :reset_password, :prepare_to_validate, on: :update, trigger: :required do
-
verifying_token :reset_password_success, :reset_password_failure
-
end
-
-
1
event :verify_and_activate, :prepare_to_validate, on: :update, trigger: :required do
-
activatable do
-
verifying_token :verify_and_activate_success, :verify_and_activate_failure
-
add_subcard(accounted)&.try :activate_accounted
-
end
-
end
-
-
1
event :password_redirect, :finalize, on: :update, when: :password_redirect? do
-
success << { id: name, view: "edit" }
-
end
-
-
# INTEGRATION
-
-
1
%i[password_reset_email verification_email welcome_email].each do |email|
-
3
event "send_#{email}".to_sym, :integrate, trigger: :required do
-
send_account_email email
-
end
-
end
-
-
## EVENT HELPERS
-
-
1
def activatable
-
abort :failure, "no field manipulation mid-activation" if subcards.present?
-
# above is necessary because activation uses super user (Decko Bot),
-
# so allowing subcards would be unsafe
-
yield
-
end
-
-
# note: this only works in the context of an action.
-
# if run independently, it will not activate an account
-
1
event :activate_account do
-
add_subfield :status, content: "active"
-
trigger_event! :send_welcome_email
-
end
-
-
1
def verifying_token success, failure
-
requiring_token do |token|
-
result = Auth::Token.decode token
-
if result.is_a?(String)
-
aborting { send failure, result }
-
else
-
send success
-
end
-
end
-
end
-
-
1
def requiring_token
-
if !(token = Env.params[:token])
-
aborting { errors.add :token, "is required" }
-
else
-
yield token
-
end
-
end
-
-
1
def password_redirect?
-
Auth.current_id == accounted_id && password.blank?
-
end
-
-
1
def verify_and_activate_success
-
Auth.signin accounted_id
-
Auth.as_bot # use admin permissions for rest of action
-
activate_account
-
success << ""
-
end
-
-
1
def verify_and_activate_failure error_message
-
send_verification_email
-
errors.add "Sorry, #{error_message}. Please check your email for a new activation link."
-
end
-
-
1
def reset_password_success
-
Auth.signin accounted_id
-
success << { id: name, view: :edit }
-
abort :success
-
end
-
-
1
def reset_password_failure error_message
-
Auth.as_bot { send_password_reset_email }
-
errors.add tr(:sorry_email_reset, error_msg: error_message)
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/account/events.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Right; module Account;
-
# Set: All "+Account+Views" cards (Views)
-
#
-
1
module Views;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/account/views.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :verify_url, cache: :never do
-
raise Error::PermissionDenied unless card.ok?(:create) || card.action
-
-
token_url :verify_and_activate, anonymous: true
-
end
-
-
1
view :reset_password_url do
-
raise Error::PermissionDenied unless card.password_card.ok? :update
-
-
token_url :reset_password
-
end
-
-
1
view :token_expiry do
-
"(#{token_expiry_sentence}"
-
end
-
-
1
view :token_days do
-
Card.config.token_expiry / 1.day
-
end
-
-
# DEPRECATED
-
1
view :verify_days, :token_days
-
1
view :reset_password_days, :token_days
-
-
1
def token_url trigger, extra_payload={}
-
card_url path(action: :update,
-
card: { trigger: trigger },
-
token: new_token(extra_payload))
-
end
-
-
1
def token_expiry_sentence
-
"Link will expire in #{render_token_days} days"
-
end
-
-
1
def new_token extra_payload
-
Auth::Token.encode card.accounted_id, extra_payload
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
[account_field_nest(:email, "email"),
-
account_field_nest(:password, "password")]
-
end
-
-
1
def account_field_nest field, title
-
field_nest field, title: title, view: :labeled
-
# edit: :inline, hide: [:help_link, :bridge_link]
-
end
-
-
1
before :content_formgroups do
-
voo.edit_structure = [[:email, "email"], [:password, "password"]]
-
end
-
-
1
view :token_expiry do
-
"<p><em>#{token_expiry_sentence}</em></p>"
-
end
-
end
-
-
2
module EmailHtmlFormat; module_parent.send :register_set_format, Card::Format::EmailHtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def mail context, fields
-
super context, fields.reverse_merge(to: card.email)
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/account/views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+ApiKey" cards
-
#
-
1
module ApiKey;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/api_key.rb"; end
-
1
include_set Abstract::AccountField
-
-
# DURATIONS = "second|minute|hour|day|week|month|year".freeze
-
-
1
def history?
-
false
-
end
-
-
1
view :raw do
-
tr :private_data
-
end
-
-
1
def validate! api_key
-
error =
-
case
-
when !real? then [:token_not_found, tr(:error_token_not_found)]
-
# when expired? then [:token_expired, tr(:error_token_expired)]
-
when content != api_key then [:incorrect_token, tr(:error_incorrect_token)]
-
end
-
errors.add(*error) if error
-
error.nil?
-
end
-
-
# def expired?
-
# !permanent? && updated_at <= term.ago
-
# end
-
#
-
# def permanent?
-
# term == "permanent"
-
# end
-
-
# def term
-
# @term ||=
-
# if expiration.present?
-
# term_from_string expiration
-
# else
-
# Card.config.token_expiry
-
# end
-
# end
-
-
# def term_from_string string
-
# string.strip!
-
# return "permanent" if string == "none"
-
# re_match = /^(\d+)[\.\s]*(#{DURATIONS})s?$/.match(string)
-
# number, unit = re_match.captures if re_match
-
# raise Card::Open::Error, tr(:exception_bad_expiration, example: '2 days') unless unit
-
# number.to_i.send unit
-
# end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/api_key.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Email" cards
-
#
-
# -*- encoding : utf-8 -*-
-
1
module Email;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/email.rb"; end
-
-
1
include_set Abstract::AccountField
-
-
1
event :validate_email, :validate, on: :save do
-
if content? && content !~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
-
errors.add :content, tr(:error_invalid_address)
-
end
-
end
-
-
1
event :validate_unique_email, after: :validate_email, on: :save do
-
if content.present?
-
Auth.as_bot do
-
cql = { right_id: EmailID, eq: content, return: :id }
-
cql[:not] = { id: id } if id
-
cql_comment = tr(:search_email_duplicate, content: content)
-
if Card.search(cql, cql_comment).first
-
errors.add :content, tr(:error_not_unique)
-
end
-
end
-
end
-
end
-
-
1
event :downcase_email, :prepare_to_validate, on: :save do
-
return if !content || content == content.downcase
-
self.content = content.downcase
-
end
-
-
1
def email_required?
-
!left.system?
-
end
-
-
1
def ok_to_read
-
if own_email? || Auth.always_ok?
-
true
-
else
-
deny_because tr(:deny_email_restricted)
-
end
-
end
-
-
1
def own_email?
-
name.part_names[0].key == Auth.as_card.key
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/email.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Password" cards
-
#
-
1
module Password;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/password.rb"; end
-
1
include_set Abstract::AccountField
-
-
1
def history?
-
false
-
end
-
-
1
def ok_to_read
-
own_account? ? true : super
-
end
-
-
1
event :encrypt_password, :store,
-
on: :save, changed: :content,
-
when: proc { !Card::Env[:no_password_encryptions] } do
-
# no_password_encryptions = hack for import - fix with api for ignoring events
-
salt = left&.salt
-
self.content = Auth.encrypt content, salt
-
-
# errors.add :password, 'need a valid salt'
-
# turns out we have a lot of existing account without a salt.
-
# not sure when that broke??
-
end
-
-
1
event :validate_password, :validate, on: :save do
-
return if content.length > 3
-
-
errors.add :password, tr(:password_length)
-
end
-
-
1
event :validate_password_present, :prepare_to_validate, on: :update do
-
abort :success if content.blank?
-
end
-
-
1
view :raw do
-
tr :encrypted
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core, wrap: :em do
-
render_raw
-
end
-
-
1
view :input do
-
card.content = ""
-
password_field :content, class: "d0-card-content", autocomplete: autocomplete?
-
end
-
-
1
def autocomplete?
-
return "on" if @parent && @parent.card.name == "*signin+*account" # HACK
-
"off"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/password.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Roles" cards
-
#
-
1
module Roles;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/roles.rb"; end
-
1
event :validate_permission_to_assign_roles, :validate, on: :save do
-
return unless (fr = forbidden_roles).present?
-
-
errors.add :permission_denied,
-
"You don't have permission to assign the role#{'s' if fr.size > 1} "\
-
"#{fr.map(&:name).to_sentence}" # LOCALIZE
-
end
-
-
1
def forbidden_roles
-
# restore old roles for permission check
-
with_old_role_permissions do |new_roles|
-
new_roles.select do |card|
-
!Card.fetch(card, "*members").ok? :update
-
end
-
end
-
end
-
-
1
def with_old_role_permissions
-
new_roles = item_cards
-
new_content = content
-
left.clear_roles
-
Auth.update_always_cache Card::Auth.as_id, nil
-
self.content = db_content_before_act
-
yield new_roles
-
ensure
-
self.content = new_content
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/roles.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Salt" cards
-
#
-
1
module Salt;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/salt.rb"; end
-
1
include_set Abstract::AccountField
-
-
1
def generate
-
self.content = Digest::SHA1.hexdigest "--#{Time.zone.now}--"
-
end
-
-
1
def history?
-
false
-
end
-
-
1
view :raw do
-
tr :private_data
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/salt.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Status" cards
-
#
-
1
module Status;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/right/status.rb"; end
-
1
include_set Abstract::AccountField
-
1
include_set Abstract::Pointer
-
-
1
def input_type
-
:radio
-
end
-
-
1
def option_names
-
%w[unapproved unverified active blocked system]
-
end
-
-
1
def ok_to_update
-
if own_account? && !Auth.always_ok?
-
deny_because you_cant(tr(:deny_not_change_own_account))
-
else
-
super
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/right/status.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Signin"
-
#
-
# The Sign In card manages logging in and out of the site.
-
#
-
1
module Signin;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/self/signin.rb"; end
-
# /:signin (core view) gives the login ui
-
# /:signin?view=edit gives the forgot password ui
-
-
# /update/:signin is the login action
-
# /delete/:signin is the logout action
-
-
# authentication event
-
1
event :signin, :validate, on: :update do
-
email = subfield :email
-
email &&= email.content
-
pword = subfield :password
-
pword &&= pword.content
-
-
authenticate_or_abort email, pword
-
end
-
-
# abort after successful signin (do not save card)
-
1
event :signin_success, after: :signin do
-
abort :success
-
end
-
-
1
event :signout, :validate, on: :delete do
-
Env.reset_session
-
Auth.signin AnonymousID
-
abort :success
-
end
-
-
# triggered by clicking "Reset my Password", this sends out the verification password
-
# and aborts (does not sign in)
-
1
event :send_reset_password_token, before: :signin, on: :update, trigger: :required do
-
email = subfield(:email)&.content
-
send_reset_password_email_or_fail email
-
end
-
-
1
def ok_to_read
-
true
-
end
-
-
1
def recaptcha_on?
-
false
-
end
-
-
1
def i18n_signin key
-
I18n.t key, scope: "mod.card-mod-account.set.self.signin"
-
end
-
-
1
def authenticate_or_abort email, pword
-
abort_unless email, :email_missing
-
abort_unless pword, :password_missing
-
authenticate_and_signin(email, pword) || failed_signin(email)
-
end
-
-
1
def authenticate_and_signin email, pword
-
return unless (account = Auth.authenticate email, pword)
-
-
Auth.signin account.left_id
-
end
-
-
1
def failed_signin email
-
errors.add :signin, signin_error_message(account_for(email))
-
abort :failure
-
end
-
-
1
def abort_unless value, error_key
-
abort :failure, i18n_signin(error_key) unless value
-
end
-
-
1
def signin_error_message account
-
case
-
when account.nil? then i18n_signin(:error_unknown_email)
-
when !account.active? then i18n_signin(:error_not_active)
-
else i18n_signin(:error_wrong_password)
-
end
-
end
-
-
1
def error_on field, error_key
-
errors.add field, i18n_signin(error_key)
-
end
-
-
1
def account_for email
-
Auth.find_account_by_email email
-
end
-
-
1
def send_reset_password_email_or_fail email
-
aborting do
-
break errors.add :email, i18n_signin(:error_blank) if email.blank?
-
-
if (account = Auth.find_account_by_email(email))&.active?
-
Auth.as_bot { account.send_password_reset_email }
-
elsif account
-
errors.add :account, i18n_signin(:error_not_active)
-
else
-
errors.add :email, i18n_signin(:error_not_recognized)
-
end
-
end
-
end
-
-
1
def send_reset_password_email_or_fail email
-
aborting do
-
break if blank_email? email
-
-
if (account = account_for email)&.active?
-
send_reset_password_email account
-
else
-
reset_password_fail account
-
end
-
end
-
end
-
-
1
def blank_email? email
-
return false if email.present?
-
-
error_on :email, :error_blank
-
end
-
-
1
def send_reset_password_email account
-
Auth.as_bot { account.send_password_reset_email }
-
end
-
-
1
def reset_password_fail account
-
if account
-
error_on :account, :error_not_active
-
else
-
error_on :email, :error_not_recognized
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core, cache: :never do
-
voo.edit_structure = [signin_field(:email), signin_field(:password)]
-
with_nest_mode :edit do
-
card_form :update, recaptcha: :off, success: signin_success do
-
[
-
_render_content_formgroups,
-
_render_signin_buttons
-
]
-
end
-
end
-
end
-
-
1
view :open do
-
voo.show :help
-
voo.hide :menu
-
super()
-
end
-
-
# FIXME: need a generic solution for this
-
1
view :title do
-
voo.title ||= I18n.t(:sign_in_title, scope: "mod.card-mod-account.set.self.signin")
-
super()
-
end
-
-
1
view :open_content do
-
# annoying step designed to avoid table of contents. sigh
-
_render_core
-
end
-
-
1
view :one_line_content do
-
""
-
end
-
-
1
view :reset_password_success do
-
# 'Check your email for a link to reset your password'
-
frame { I18n.t(:check_email, scope: "mod.card-mod-account.set.self.signin") }
-
end
-
-
1
view :signin_buttons do
-
button_formgroup do
-
[signin_button, signup_link, reset_password_link]
-
end
-
end
-
-
# FORGOT PASSWORD
-
1
view :edit do
-
reset_password_voo
-
Auth.as_bot { super() }
-
end
-
-
1
def reset_password_voo
-
voo.title ||= card.i18n_signin(:forgot_password)
-
voo.edit_structure = [signin_field(:email)]
-
voo.hide :help
-
end
-
-
1
view :edit_buttons do
-
text = I18n.t :reset_my_password, scope: "mod.card-mod-account.set.self.signin"
-
button_tag text, situation: "primary", class: "_close-modal-on-success"
-
end
-
-
1
def signin_success
-
"REDIRECT: #{Env.interrupted_action || '*previous'}"
-
end
-
-
1
def signin_button
-
text = I18n.t :sign_in, scope: "mod.card-mod-account.set.self.signin"
-
button_tag text, situation: "primary"
-
end
-
-
1
def signup_link
-
text = I18n.t :or_sign_up, scope: "mod.card-mod-account.set.self.signin"
-
subformat(Card[:account_links]).render! :sign_up, title: text
-
end
-
-
1
def reset_password_link
-
text = I18n.t :reset_password, scope: "mod.card-mod-account.set.self.signin"
-
link = link_to_view :edit, text, path: { slot: { hide: :bridge_link } }
-
# FIXME: inline styling
-
raw("<div style='float:right'>#{link}</div>")
-
end
-
-
1
def edit_view_hidden
-
hidden_tags card: { trigger: :send_reset_password_token }
-
end
-
-
1
def edit_success
-
{ view: :reset_password_success }
-
end
-
-
1
def signin_field name
-
nest_name = "".to_name.trait(name)
-
[nest_name, { title: name.to_s, view: "titled",
-
nest_name: nest_name, skip_perms: true }]
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/self/signin.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Role" cards
-
#
-
1
module Role;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/type/role.rb"; end
-
1
def disabled?
-
Auth.current&.fetch(:disabled_roles)&.item_ids&.include? id
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :link_with_checkbox, cache: :never do
-
role_checkbox
-
end
-
-
1
def role_checkbox
-
name = card.disabled? ? "add_item" : "drop_item"
-
subformat(Auth.current.field(:disabled_roles, new: {})).card_form :update do
-
[check_box_tag(name, card.id, !card.disabled?, class: "_edit-item"),
-
render_link]
-
end
-
end
-
-
1
def related_by_content_items
-
super.unshift ["members", :members]
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/type/role.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Signup" cards
-
#
-
1
module Signup;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/type/signup.rb"; end
-
1
include_set Abstract::Accountable
-
-
1
require_field :account
-
-
1
def default_account_status
-
can_approve? ? "unverified" : "unapproved"
-
end
-
-
1
def can_approve?
-
Card.new(type_id: Card.default_accounted_type_id).ok? :create
-
end
-
-
1
def activate_accounted
-
self.type_id = Card.default_accounted_type_id
-
end
-
-
1
event :auto_approve_with_verification, :validate, on: :create, when: :can_approve? do
-
request_verification
-
end
-
-
1
event :approve_with_verification, :validate, on: :update, trigger: :required do
-
approvable { request_verification }
-
end
-
-
1
event :approve_without_verification, :validate, on: :update, trigger: :required do
-
# TODO: if validated here, add trigger and activate in storage phase
-
approvable do
-
activate_accounted
-
account_subfield.activate_account
-
end
-
end
-
-
1
event :act_as_current_for_integrate_stage, :integrate, on: :create do
-
# needs justification!
-
Auth.current_id = id
-
end
-
-
1
def account_subfield
-
subfield(:account) || add_subfield(:account)
-
end
-
-
1
def request_verification
-
acct = account_subfield
-
acct.add_subfield :status, content: "unverified"
-
acct.trigger_event! :send_verification_email
-
end
-
-
1
def approvable
-
if can_approve?
-
yield
-
else
-
abort :failure, "illegal approval" # raise permission denied?
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/type/signup.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Type; module Signup;
-
# Set: All "Signup+Views" cards (Views)
-
#
-
1
module Views;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/type/signup/views.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def invitation?
-
Auth.signed_in? && card.can_approve?
-
end
-
-
1
view :new do
-
voo.title = invitation? ? tr(:invite) : tr(:sign_up)
-
super()
-
end
-
-
1
view :content_formgroups do
-
[account_formgroups, (card.structure ? edit_slot : "")].join
-
end
-
-
1
view :new_buttons do
-
button_formgroup do
-
[standard_create_button, invite_button].compact
-
end
-
end
-
-
1
def invite_button
-
return unless invitation?
-
button_tag "Send Invitation", situation: "primary"
-
end
-
-
1
view :core, template: :haml do
-
@lines = [signup_line] + account_lines
-
@body = process_content _render_raw
-
end
-
-
1
def signup_line
-
["<strong>#{safe_name}</strong>",
-
("was" if invited?),
-
"signed up on #{format_date card.created_at}"].compact.join " "
-
end
-
-
1
def invited?
-
!self_signup?
-
end
-
-
1
def self_signup?
-
card.creator_id == AnonymousID
-
end
-
-
1
def account_lines
-
if card.account
-
verification_lines
-
else
-
[tr(:missing_account)]
-
end
-
end
-
-
1
def verification_lines
-
[verification_sent_line, verification_link_line].compact
-
end
-
-
1
def verification_sent_line
-
account = card.account
-
return unless account.email_card.ok?(:read)
-
"A verification email has been sent to #{account.email}"
-
end
-
-
1
def verification_link_line
-
links = verification_links
-
return if links.empty?
-
links.join " "
-
end
-
-
1
def verification_links
-
[approve_with_token_link, approve_without_token_link, deny_link].compact
-
end
-
-
1
def approve_with_token_link
-
action = card.account.status == "unverified" ? "Resend" : "Send"
-
approval_link "#{action} verification email", :with
-
end
-
-
1
def approve_without_token_link
-
approval_link "Approve without verification", :without
-
end
-
-
1
def approval_link text, with_or_without
-
return unless card.can_approve?
-
link_to_card card, text,
-
path: { action: :update,
-
card: { trigger: "approve_#{with_or_without}_verification" } }
-
end
-
-
1
def deny_link
-
return unless card.ok? :delete
-
link_to_card card, "Deny and delete", path: { action: :delete }
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/type/signup/views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "User" cards
-
#
-
1
module User;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/type/user.rb"; end
-
1
include Basic
-
1
include_set Abstract::Accountable
-
-
1
attr_accessor :email
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :setup, unknown: true, perms: ->(_fmt) { Auth.needs_setup? } do
-
with_nest_mode :edit do
-
voo.title = "Your deck is ready to go!" # LOCALIZE
-
voo.show! :help
-
voo.hide! :menu
-
voo.help = haml :setup_help
-
Auth.as_bot { setup_form }
-
end
-
end
-
-
1
def setup_form
-
frame_and_form :create do
-
[
-
setup_hidden_fields,
-
_render_name_formgroup,
-
account_formgroups,
-
setup_form_buttons
-
]
-
end
-
end
-
-
1
def setup_form_buttons
-
button_formgroup { setup_button }
-
end
-
-
1
def setup_button
-
submit_button text: "Set up", disable_with: "Setting up"
-
end
-
-
1
def setup_hidden_fields
-
hidden_tags(
-
setup: true,
-
success: "REDIRECT: #{path mark: ''}",
-
"card[type_id]" => Card.default_accounted_type_id
-
)
-
end
-
end
-
-
1
def setup?
-
Card::Env.params[:setup]
-
end
-
-
1
event :setup_as_bot, before: :check_permissions, on: :create, when: :setup? do
-
abort :failure unless Auth.needs_setup?
-
Auth.as_bot
-
# we need bot authority to set the initial administrator roles
-
# this is granted and inspected here as a separate event for
-
# flexibility and security when configuring initial setups
-
end
-
-
1
event :setup_first_user, :prepare_to_store, on: :create, when: :setup? do
-
add_subcard "signup alert email+*to", content: name
-
add_subfield :roles, content: roles_for_first_user
-
end
-
-
1
def roles_for_first_user
-
%i[help_desk shark administrator].map(&:cardname)
-
end
-
-
1
event :signin_after_setup, :integrate, on: :create, when: :setup? do
-
Auth.signin id
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/type/user.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class TypePlusRight; module User;
-
# Set: All "+Email" cards on "User" cards
-
#
-
# supports legacy references to <User>+*email
-
1
module Email;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-account/set/type_plus_right/user/email.rb"; end
-
# (standard representation is now <User>+*account+*email)
-
1
view :raw do
-
card.content_email || card.account_email || ""
-
end
-
-
1
def content_email
-
content if real?
-
end
-
-
1
def account_email
-
left&.account&.email
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-account/set/type_plus_right/user/email.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (AccountDropdown)
-
#
-
1
module AccountDropdown;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/abstract/account_dropdown.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def link_to_mycard
-
15
link_to_card Auth.current.name, nil,
-
id: "my-card-link", class: "nav-link #{classy('my-card')}"
-
end
-
-
1
def account_dropdown &render_role_item
-
15
split_button link_to_mycard, nil do
-
[
-
15
link_to_card([Auth.current, :account_settings], "Account"),
-
15
(["Roles", role_items(&render_role_item)] if special_roles?)
-
]
-
end
-
end
-
-
1
def special_roles?
-
15
Auth.current_roles.size > 1
-
end
-
-
1
def role_items
-
12
Auth.current_roles.map do |role_name|
-
28
yield role_name
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/abstract/account_dropdown.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Pointer;
-
# Set: Abstract (Pointer, HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/abstract/pointer/html_views.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :nav_item do
-
23
nav_dropdown
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/abstract/pointer/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (NavbarLinks)
-
#
-
1
module NavbarLinks;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/all/navbar_links.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :navbar_links, perms: :none do
-
46
wrap_with :ul, class: "navbar-nav" do
-
46
navbar_items
-
end
-
end
-
-
# Iterates over all nests and links and renders them as bootstrap navbar items.
-
# Items that are pointer cards become dropdowns
-
1
def navbar_items view: :nav_item, link_class: "nav-link"
-
46
process_content nil, chunk_list: :references do |chunk|
-
184
case chunk
-
when Card::Content::Chunk::Link
-
184
link = chunk.render_link view: view, explicit_link_opts: { class: link_class }
-
184
chunk.explicit_link? && view == :nav_item ? wrap_with_nav_item(link) : link
-
when Card::Content::Chunk::Nest
-
content_nest chunk.options.merge view: view
-
else
-
chunk.process_chunk
-
end
-
end
-
end
-
-
# overridden in Abstact::Pointer to render dropdown
-
1
view :nav_item do
-
23
wrap_with_nav_item link_view(class: "nav-link")
-
end
-
-
1
def wrap_with_nav_item content
-
115
wrap_with(:li, content, class: "nav-item")
-
end
-
-
1
view :nav_link_in_dropdown do
-
46
link_to_card card, render_title, class: "dropdown-item"
-
end
-
-
1
def nav_dropdown
-
23
wrap_with(:li, class: "nav-item dropdown") do
-
[
-
23
dropdown_toggle_link,
-
dropdown_menu
-
]
-
end
-
end
-
-
1
def dropdown_toggle_link
-
23
link_to(render_title, href: "#", class: "nav-link dropdown-toggle",
-
"data-toggle": "dropdown")
-
end
-
-
1
def dropdown_menu
-
23
wrap_with :div, dropdown_menu_items, class: "dropdown-menu"
-
end
-
-
1
def dropdown_menu_items
-
23
navbar_items view: :nav_link_in_dropdown, link_class: "dropdown-item"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/all/navbar_links.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+EnabledRoles" cards
-
#
-
1
module EnabledRoles;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/right/enabled_roles.rb"; end
-
1
include_set Abstract::AccountDropdown
-
-
1
def ok_to_read
-
true
-
end
-
-
1
def ok_to_update
-
left_id == Auth.current_id
-
end
-
-
1
def ok_to_create
-
left_id == Auth.current_id
-
end
-
-
1
def ensure_roles
-
12
self.content = Auth.current_roles.to_pointer_content if content.blank?
-
end
-
-
1
event :validate_role_enabling, :validate, on: :save do
-
illegal_roles = item_names - Auth.current_roles
-
return if illegal_roles.empty?
-
-
errors.add :content, "illegal roles: #{illegal_roles.to_sentence}" # LOCALIZE
-
end
-
-
1
event :clear_roles_cache, :prepare_to_store, before: :store_in_session do
-
clear_roles
-
Auth.update_always_cache Auth.as_id, nil
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# permission change compared to super
-
1
view :edit_inline, perms: :none, unknown: true, cache: :never, wrap: :slot do
-
12
super()
-
end
-
-
1
def input_type
-
12
:checkbox
-
end
-
-
1
def edit_success
-
12
{ reload: true }
-
end
-
-
1
def hidden_form_tags _action, opts
-
12
"#{super} #{hidden_tags card: { type_id: SessionID }}"
-
end
-
-
1
def checkbox_input
-
12
card.ensure_roles
-
12
wrap_with :div, class: "pointer-checkbox-list" do
-
12
account_dropdown &method(:role_item_checkbox)
-
end
-
end
-
-
1
def role_item_checkbox role_name
-
28
haml :role_checkbox, id: "pointer-checkbox-#{role_name.to_name.key}",
-
checked: card.item_names.include?(role_name),
-
option_name: role_name
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/right/enabled_roles.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "AccountLinks"
-
#
-
1
module AccountLinks;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/self/account_links.rb"; end
-
1
include_set Abstract::AccountDropdown
-
-
1
def ok_to_read
-
true
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core, cache: :never do
-
status_class = Auth.signed_in? ? "logged-in" : "logged-out"
-
wrap_with :div, id: "logging", class: status_class do
-
navbar_items.join "\n"
-
end
-
end
-
-
1
def navbar_items
-
# removed invite for now
-
links =
-
23
%i[my_card sign_out sign_up sign_in].map do |link_view|
-
92
render(link_view)
-
end.compact
-
-
23
links.map do |link|
-
92
wrap_with_nav_item link
-
end
-
end
-
-
1
def self.link_options opts={}
-
5
options = { denial: :blank, cache: :never }.merge opts
-
97
options[:perms] = ->(r) { yield r } if block_given?
-
5
options.clone
-
end
-
-
1
view :sign_up, link_options(&:show_signup_link?) do
-
8
link_to_card :signup, account_link_text(:sign_up),
-
class: nav_link_class("signup-link"),
-
path: { action: :new, mark: :signup }
-
end
-
-
24
view(:sign_in, link_options { !Auth.signed_in? }) do
-
8
link_to_card :signin, account_link_text(:sign_in),
-
class: nav_link_class("signin-link")
-
end
-
-
24
view(:sign_out, link_options { Auth.signed_in? }) do
-
15
link_to_card :signin, account_link_text(:sign_out),
-
class: nav_link_class("signout-link"),
-
path: { action: :delete }
-
end
-
-
1
view :invite, link_options(&:show_invite_link?) do
-
link_to_card :signup, account_link_text(:invite),
-
class: nav_link_class("invite-link"),
-
path: { action: :new, mark: :signup }
-
end
-
-
24
view(:my_card, link_options { Auth.signed_in? }) do
-
15
can_disable_roles? ? interactive_roles_dropdown : simple_roles_dropdown
-
end
-
-
1
def interactive_roles_dropdown
-
12
nest(enabled_roles_card,
-
view: :edit_inline, hide: %i[edit_inline_buttons name_formgroup])
-
end
-
-
1
def simple_roles_dropdown
-
3
account_dropdown(&method(:link_to_card))
-
end
-
-
1
def enabled_roles_card
-
12
Auth.current.fetch :enabled_roles, new: { type_id: SessionID }
-
end
-
-
1
def role_list
-
Auth.current_roles.map(&method(:link_to_card))
-
end
-
-
1
def can_disable_roles?
-
15
Auth.current_roles.size > 1 &&
-
Card::Codename.exists?(:enabled_roles) # workaround for broken migrations
-
end
-
-
1
def account_link_text purpose
-
31
voo.title ||
-
I18n.t(purpose, scope: "mod.card-mod-account.set.self.account_links")
-
end
-
-
1
def nav_link_class type
-
31
"nav-link #{classy(type)}"
-
end
-
-
1
def show_signup_link?
-
23
!Auth.signed_in? && Card.new(type_id: SignupID).ok?(:create)
-
end
-
-
1
def show_invite_link?
-
Auth.signed_in? &&
-
Card.new(type_id: Card.default_accounted_type_id).ok?(:create)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/self/account_links.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "DropdownDivider"
-
#
-
1
module DropdownDivider;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/self/dropdown_divider.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :nav_item do
-
wrap_with :div, "", class: "dropdown-divider"
-
end
-
-
1
view :nav_link_in_dropdown do
-
23
wrap_with :div, "", class: "dropdown-divider"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/self/dropdown_divider.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Navbox"
-
#
-
1
module Navbox;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/self/navbox.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :navbox, cache: :never do
-
23
select_tag "query[keyword]", "", class: "_navbox navbox form-control w-100",
-
placeholder: navbar_placeholder
-
end
-
-
1
view :navbar do
-
# FIXME: not bootstrap class here.
-
23
class_up "navbox-form", "form-inline"
-
23
render_core
-
end
-
-
1
view :core do
-
23
form_tag path(mark: :search), method: "get", role: "search",
-
class: classy("navbox-form", "nodblclick") do
-
23
wrap_with :div, class: "form-group w-100" do
-
23
render_navbox
-
end
-
end
-
end
-
-
# def initial_options
-
# return "" unless (keyword = params.dig :query, :keyword)
-
# options_for_select [keyword]
-
# end
-
-
# TODO: the more natural placeholder would be the content of the navbox card, no?
-
# Also, the forced division of "raw" and "core" should probably be replaced
-
# with a single haml template (for core view)
-
1
def navbar_placeholder
-
23
@@placeholder ||= begin
-
1
holder_card = Card["#{Card[:navbox].name}+*placeholder"]
-
1
holder_card ? holder_card.content : "Search"
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/self/navbox.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Html" cards
-
#
-
1
module Html;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card/mod/navbar/set/type/html.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# deprecated; here to support old "*main menu" html cards in existing decks
-
1
view :navbar_links, perms: :none do
-
wrap_with :ul, class: "navbar-nav" do
-
item_links.map do |link|
-
wrap_with(:li, class: "nav-item") { link }
-
end.join "\n"
-
end
-
end
-
-
1
def item_links _args={}
-
raw(render_core).split(/[,\n]/)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/navbar/set/type/html.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Bridge)
-
#
-
1
module Bridge;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge.rb"; end
-
1
BRIDGE_TABS = { "Account" => :account_tab,
-
"Guide" => :guide_tab,
-
"Engage" => :engage_tab,
-
"History" => :history_tab,
-
"Related" => :related_tab,
-
"Rules" => :rules_tab }.freeze
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
wrapper :bridge do
-
1
class_up "modal-dialog", "no-gaps"
-
1
voo.hide! :modal_footer
-
1
wrap_with_modal size: :full, title: bridge_breadcrumbs do
-
1
haml :bridge
-
end
-
end
-
-
1
def bridge_tabs
-
1
wrap do
-
1
tabs(visible_bridge_tabs, bridge_tab, load: :lazy) { _render bridge_tab }
-
end
-
end
-
-
1
def bridge_tab
-
1
@bridge_tab ||= bridge_param :tab
-
end
-
-
1
def bridge_param key
-
1
params.dig(:bridge, key)&.to_sym || try("default_bridge_#{key}")
-
end
-
-
1
def bridge_breadcrumbs
-
1
<<-HTML.strip_heredoc
-
<nav aria-label="breadcrumb">
-
<ol class="breadcrumb _bridge-breadcrumb">
-
<li class="breadcrumb-item">#{card.name}</li>
-
<li class="breadcrumb-item active">Edit</li>
-
</ol>
-
</nav>
-
HTML
-
end
-
-
1
def bridge_link_opts opts={}
-
opts[:"data-slot-selector"] = bridge_slot_selector
-
opts[:remote] = true
-
add_class opts, "slotter"
-
opts.bury :path, :layout, :overlay
-
opts[:path][:view] ||= :content
-
opts
-
end
-
-
1
def bridge_slot_selector
-
".bridge-main > .overlay-container > .card-slot._bottomlay-slot," \
-
".bridge-main > ._overlay-container-placeholder > .card-slot"
-
end
-
-
1
def default_bridge_tab
-
1
show_guide_tab? ? :guide_tab : :engage_tab
-
end
-
-
1
def breadcrumb_data title, html_class=nil
-
html_class ||= title.underscore
-
{ "data-breadcrumb": title, "data-breadcrumb-class": html_class }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bridge;
-
# Set: All cards (Bridge, BridgePills)
-
#
-
1
module BridgePills;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/bridge_pills.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
BRIDGE_PILL_UL_CLASSES =
-
1
"nav nav-pills _auto-single-select bridge-pills flex-column".freeze
-
-
1
BRIDGE_PILL_LI_CLASSES = "nav-item".freeze
-
-
1
def bridge_pills items
-
list_tag class: BRIDGE_PILL_UL_CLASSES, items: { class: BRIDGE_PILL_LI_CLASSES } do
-
items
-
end
-
end
-
-
1
def bridge_pill_items data, breadcrumb
-
data.map do |text, field, extra_opts|
-
opts = bridge_pill_item_opts breadcrumb, extra_opts, text
-
mark = opts.delete(:mark) == :absolute ? field : [card, field]
-
link_to_card mark, text, opts
-
end
-
end
-
-
1
def bridge_pill_item_opts breadcrumb, extra_opts, text
-
opts = bridge_link_opts.merge("data-toggle": "pill")
-
opts.merge! breadcrumb_data(breadcrumb)
-
-
if extra_opts
-
classes = extra_opts.delete :class
-
add_class opts, classes if classes
-
opts.deep_merge! extra_opts
-
end
-
opts["data-cy"] = "#{text.to_name.key}-pill"
-
add_class opts, "nav-link"
-
opts
-
end
-
-
1
def bridge_pill_sections tab_name
-
wrap_with :ul, class: BRIDGE_PILL_UL_CLASSES do
-
yield.map { |args| bridge_pill_section(tab_name, *args) }
-
end
-
end
-
-
1
def bridge_pill_section tab_name, title, items
-
wrap_with(:h6, title, class: "ml-1 mt-3") +
-
wrap_each_with(:li, class: BRIDGE_PILL_LI_CLASSES) do
-
bridge_pill_items(items, tab_name)
-
end.html_safe
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/bridge_pills.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bridge;
-
# Set: All cards (Bridge, FollowSection)
-
#
-
1
module FollowSection;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/follow_section.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def follow_section
-
return unless show_follow?
-
-
wrap_with :div, class: "mb-3" do
-
[follow_button_group, followers_bridge_link, follow_overview_button]
-
end
-
end
-
-
1
def follow_button_group
-
wrap_with :div, class: "btn-group btn-group-sm follow-btn-group" do
-
[follow_button, follow_advanced]
-
end
-
end
-
-
1
def follow_overview_button
-
link_to_card [Auth.current, :follow], "all followed cards",
-
bridge_link_opts(class: "btn btn-sm btn-secondary",
-
"data-cy": "follow-overview")
-
end
-
-
1
def follow_advanced
-
opts = bridge_link_opts(class: "btn btn-sm btn-primary",
-
path: { view: :overlay_rule },
-
"data-cy": "follow-advanced")
-
opts[:path].delete :layout
-
link_to_card card.follow_rule_card(Auth.current.name, new: {}),
-
icon_tag("more_horiz"), opts
-
end
-
-
1
def followers_bridge_link
-
cnt = card.followers_count
-
link_to_card card.name.field(:followers), "#{cnt} follower#{'s' unless cnt == 1}",
-
bridge_link_opts(class: "btn btn-sm ml-2 btn-secondary slotter",
-
remote: true, "data-cy": "followers")
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/follow_section.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bridge;
-
# Set: All cards (Bridge, RelatedSection)
-
#
-
1
module RelatedSection;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/related_section.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
RELATED_ITEMS =
-
{
-
1
"by name" => [["children", :children],
-
["mates", :mates]],
-
# FIXME: optimize,
-
"by content" => [["links out", :links_to],
-
["links in", :linked_to_by],
-
["nests", :nests],
-
["nested by", :nested_by],
-
["references out", :refers_to],
-
["references in", :referred_to_by]]
-
# ["by edit", [["creator", :creator],
-
# ["editors", :editors],
-
# ["last edited", :last_edited]]]
-
}.freeze
-
-
1
def related_by_name_items
-
pills = []
-
if card.name.junction?
-
pills += card.name.ancestors.map { |a| [a, a, { mark: :absolute }] }
-
end
-
pills += RELATED_ITEMS["by name"]
-
pills
-
end
-
-
1
def related_by_content_items
-
RELATED_ITEMS["by content"]
-
end
-
-
1
def related_by_type_items
-
[["#{card.type} cards", [card.type, :type, :by_name], mark: :absolute]]
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/related_section.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bridge;
-
# Set: All cards (Bridge, TabViews)
-
#
-
1
module TabViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/tab_views.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :engage_tab, wrap: { div: { class: "m-3 mt-4 _engage-tab" } }, cache: :never do
-
[render_follow_section, discussion_section].compact
-
end
-
-
1
view :history_tab, wrap: :slot do
-
class_up "d0-card-body", "history-slot"
-
voo.hide :act_legend
-
acts_bridge_layout card.history_acts
-
end
-
-
1
view :related_tab do
-
bridge_pill_sections "Related" do
-
%w[name content type].map do |section_name|
-
["by #{section_name}", send("related_by_#{section_name}_items")]
-
end
-
end
-
end
-
-
1
view :rules_tab, unknown: true do
-
class_up "card-slot", "flex-column"
-
wrap do
-
nest current_set_card, view: :bridge_rules_tab
-
end
-
end
-
-
1
view :follow_section, wrap: :slot, cache: :never do
-
follow_section
-
end
-
-
1
view :guide_tab, unknown: true do
-
render_guide
-
end
-
-
1
def discussion_section
-
return unless show_discussion?
-
-
field_nest(:discussion, view: :titled, title: "Discussion", show: :comment_box,
-
hide: [:menu])
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/tab_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bridge;
-
# Set: All cards (Bridge, TabVisibility)
-
#
-
1
module TabVisibility;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/tab_visibility.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def visible_bridge_tabs
-
1
Bridge::BRIDGE_TABS.select do |_title, view|
-
6
send "show_#{view}?"
-
end
-
end
-
-
1
private
-
-
1
def show_engage_tab?
-
1
return unless card.real?
-
-
1
show_follow? || show_discussion?
-
end
-
-
1
def show_account_tab?
-
1
false
-
end
-
-
1
def show_history_tab?
-
1
card.real?
-
end
-
-
1
def show_related_tab?
-
1
card.real?
-
end
-
-
1
def show_rules_tab?
-
1
true
-
end
-
-
1
def show_guide_tab?
-
2
guide.present?
-
end
-
-
1
def show_discussion?
-
d_card = discussion_card
-
return unless d_card
-
-
permission_task = d_card.new_card? ? :update : :read
-
d_card.ok? permission_task
-
end
-
-
1
def discussion_card?
-
card.junction? && card.name.tag_name.key == :discussion.cardname.key
-
end
-
-
1
def discussion_card
-
return if card.new_card? || discussion_card?
-
-
card.fetch :discussion, skip_modules: true, new: {}
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/bridge/tab_visibility.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EditContent)
-
#
-
1
module EditContent;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_content.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :edit_form, wrap: :slot do
-
voo.show :edit_type_row
-
with_nest_mode :edit do
-
edit_form
-
end
-
end
-
-
1
def edit_form
-
voo.hide :edit_type_row
-
form_opts = edit_form_opts.reverse_merge success: edit_success
-
card_form(:update, form_opts) do
-
[
-
edit_view_hidden,
-
_render_edit_type_row(home_view: :edit_type_row),
-
# home_view is necessary for cancel to work correctly.
-
# it seems a little strange to have to think about home_view here,
-
# but the issue is that something currently has to happen prior to the
-
# render to get voo.slot_options to have the write home view in
-
# the slot wrap. Id think this would probably best be handled as an
-
# option to #wrap that triggers a new heir voo
-
_render_content_formgroups,
-
_render_edit_buttons
-
]
-
end
-
end
-
-
1
view :edit, perms: :update, unknown: true, cache: :never,
-
wrap: { modal: { footer: "",
-
size: :edit_modal_size,
-
title: :render_title,
-
menu: :edit_modal_menu } } do
-
add_name_context
-
with_nest_mode :edit do
-
voo.show :help
-
voo.hide :save_button
-
wrap true do
-
[
-
frame_help,
-
_render_edit_form
-
]
-
end
-
end
-
end
-
-
1
def edit_modal_size
-
:large
-
end
-
-
1
def edit_modal_menu
-
wrap_with_modal_menu do
-
[close_modal_window, render_bridge_link]
-
end
-
end
-
-
1
def edit_form_opts
-
# for override
-
{ "data-slot-selector": "modal-origin", "data-slot-error-selector": ".card-slot" }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_content.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EditInline)
-
#
-
1
module EditInline;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_inline.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :edit_inline, perms: :update, unknown: true, cache: :never, wrap: :slot do
-
12
voo.hide :name_formgroup, :type_formgroup
-
12
with_nest_mode :edit do
-
12
card_form :update, success: edit_success do
-
[
-
12
edit_view_hidden,
-
_render_content_formgroups,
-
_render_edit_inline_buttons
-
]
-
end
-
end
-
end
-
-
1
view :edit_name_row do
-
edit_row_fixed_width "Name", card.name, :name_form
-
end
-
-
1
view :edit_inline_buttons do
-
button_formgroup do
-
wrap_with "div", class: "d-flex" do
-
[standard_save_button, cancel_in_place_button, delete_button]
-
end
-
end
-
end
-
-
# TODO: better styling for this so that is reusable
-
# At the moment it is used for the name and type field in the bridge
-
# (with fixed 50px width for the title column) and
-
# for password and email for accounts (with fixed 75px width for the title column)
-
# The view is very similar to labeled but with fixed edit link on the right
-
# and a fixed width for the labels so that the content column is aligned
-
# There is also the problem that label and content are not vertically aligned
-
1
view :edit_row do
-
edit_row_fixed_width render_title, render_core, :edit_inline, 75
-
end
-
-
1
def edit_row_fixed_width title, content, edit_view, width=50
-
class_up "card-slot", "d-flex"
-
wrap do
-
["<label class='w-#{width}px'>#{title}</label>",
-
content,
-
edit_inline_link(edit_view, align: :right)]
-
end
-
end
-
-
1
def edit_inline_link view=:edit_inline, align: :left
-
align = align == :left ? "ml-2" : "ml-auto"
-
link_to_view view, menu_icon, class: "#{align} edit-link", "data-cy": "edit-link"
-
end
-
-
1
def cancel_in_place_button args={}
-
args.reverse_merge! class: "cancel-button btn-sm", href: path
-
cancel_button args
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_inline.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EditName)
-
#
-
1
module EditName;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_name.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# note: depends on js with selector ".edit_name-view .card-form"
-
1
view :edit_name, perms: :update do
-
frame { name_form }
-
end
-
-
# note: depends on js with selector ".name_form-view .card-form"
-
1
view :name_form, perms: :update, wrap: :slot, cache: :never do
-
name_form :edit_name_row
-
end
-
-
1
def name_form success_view=nil
-
card_form({ action: :update, id: card.id },
-
# "main-success" => "REDIRECT",
-
"data-update-origin": "true",
-
success: edit_name_success(success_view)) do
-
[hidden_edit_name_fields,
-
_render_name_formgroup,
-
rename_confirmation_alert,
-
edit_name_buttons]
-
end
-
end
-
-
1
def edit_name_success view=nil
-
success = { id: "_self" }
-
success[:view] = view if view
-
success
-
end
-
-
1
def hidden_edit_name_fields
-
hidden_tags old_name: card.name, card: { update_referers: false }
-
end
-
-
1
def edit_name_buttons
-
button_formgroup do
-
[rename_and_update_button, rename_button, standard_cancel_button]
-
end
-
end
-
-
# LOCALIZE
-
1
def rename_and_update_button
-
submit_button text: "Rename and Update", disable_with: "Renaming",
-
class: "renamer-updater"
-
end
-
-
1
def rename_button
-
button_tag "Rename", data: { disable_with: "Renaming" }, class: "renamer"
-
end
-
-
# LOCALIZE
-
1
def rename_confirmation_alert
-
msg = "<h5>Are you sure you want to rename <em>#{safe_name}</em>?</h5>"
-
msg << %(<h6>This may change names referred to by other cards.</h6>)
-
msg << %(<p>You may choose to <em>update or ignore</em> the referers.</p>)
-
msg << hidden_field_tag(:referers, 1)
-
alert("warning", false, false, class: "hidden-alert") { msg }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_name.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EditType)
-
#
-
1
module EditType;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_type.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :edit_type, cache: :never, perms: :update do
-
frame do
-
_render_edit_type_form
-
end
-
end
-
-
1
view :edit_type_form, cache: :never, perms: :update, wrap: :slot do
-
card_form :update, success: edit_type_success do
-
[type_formgroup, render_new_buttons]
-
end
-
end
-
-
1
def edit_type_success
-
{ view: :core }
-
end
-
-
1
view :edit_type_row do
-
return _render_bridge_type_formgroup if voo.visible?(:type_form) { false }
-
-
edit_row_fixed_width "Type", link_to_card(card.type), :bridge_type_formgroup
-
end
-
-
1
view :bridge_type_formgroup, unknown: true, wrap: :slot do
-
type_formgroup href: path(mark: card.id,
-
view: :edit_form,
-
assign: true,
-
slot: { show: :type_form }),
-
class: "live-type-field slotter",
-
'data-remote': true,
-
'data-slot-selector': ".card-slot.edit_form-view"
-
end
-
-
1
view :type_formgroup do
-
type_formgroup
-
end
-
-
1
def type_formgroup args={}
-
add_class args, "type-field"
-
wrap_type_formgroup do
-
type_field args
-
end
-
end
-
-
1
def wrap_type_formgroup
-
7
formgroup "Type", input: "type", class: "type-formgroup", help: false do
-
7
output [yield, hidden_field_tag(:assign, true)]
-
end
-
end
-
-
1
def type_field args={}
-
7
typelist = Auth.createable_types
-
7
current_type = type_field_current_value args, typelist
-
7
action_view.select_tag "card[type]", type_field_options(current_type),
-
args.merge("data-select2-id": "#{unique_id}-#{Time.now.to_i}")
-
end
-
-
1
def type_field_options current_type
-
7
types = grouped_types(current_type)
-
-
7
if types.size == 1
-
options_for_select types.flatten[1], current_type
-
else
-
7
grouped_options_for_select types, current_type
-
end
-
end
-
-
1
def grouped_types current_type
-
70
groups = Hash.new { |h, k| h[k] = [] }
-
7
allowed = ::Set.new Auth.createable_types
-
7
allowed << current_type if current_type
-
-
7
visible_cardtype_groups.each_pair do |name, items|
-
63
if name == "Custom"
-
7
Auth.createable_types.each do |type|
-
301
groups["Custom"] << type unless ::Card::Set::Self::Cardtype::GROUP_MAP[type]
-
end
-
else
-
56
items.each do |i|
-
259
groups[name] << i if allowed.include?(i)
-
end
-
end
-
end
-
7
groups
-
end
-
-
1
def visible_cardtype_groups
-
7
::Card::Set::Self::Cardtype::GROUP
-
end
-
-
1
def type_field_current_value args, typelist
-
7
return if args.delete :no_current_type
-
-
7
if !card.new_card? && !typelist.include?(card.type_name)
-
# current type should be an option on existing cards,
-
# regardless of create perms
-
typelist.push(card.type_name).sort!
-
end
-
7
card.type_name_or_default
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/edit_type.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Editing)
-
#
-
1
module Editing;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/editing.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
###---( TOP_LEVEL (used by menu) NEW / EDIT VIEWS )
-
1
view :bridge, perms: :update, unknown: true, cache: :never, wrap: :bridge do
-
with_nest_mode :edit do
-
add_name_context
-
voo.show :help
-
wrap true, breadcrumb_data("Editing", "edit") do
-
bridge_parts
-
end
-
end
-
end
-
-
1
view :cardboard, :bridge
-
-
1
def bridge_parts
-
voo.show! :edit_type_row
-
-
[
-
frame_help,
-
_render_edit_name_row(home_view: :edit_name_row),
-
# home_view is necessary for cancel to work correctly.
-
# it seems a little strange to have to think about home_view here,
-
# but the issue is that something currently has to happen prior to the
-
# render to get voo.slot_options to have the write home view in
-
# the slot wrap. I think this would probably best be handled as an
-
# option to #wrap that triggers a new heir voo
-
_render_edit_form
-
]
-
end
-
-
1
def edit_success
-
# for override
-
end
-
-
1
def edit_view_hidden
-
# for override
-
end
-
-
1
view :edit_buttons do
-
button_formgroup do
-
wrap_with "div", class: "d-flex" do
-
[standard_submit_button, edit_cancel_button, delete_button]
-
end
-
end
-
end
-
-
# TODO: add undo functionality
-
1
view :just_deleted, unknown: true do
-
wrap { "#{render_title} deleted" }
-
end
-
-
1
view :edit_rules, cache: :never, unknown: true do
-
nest current_set_card, view: :bridge_rules_tab
-
end
-
-
1
view :edit_structure, cache: :never do
-
return unless card.structure
-
-
nest card.structure_rule_card, view: :edit
-
# FIXME: this stuff:
-
# slot: {
-
# cancel_slot_selector: ".card-slot.related-view",
-
# cancel_path: card.format.path(view: :edit), hide: :edit_toolbar,
-
# hidden: { success: { view: :open, "slot[subframe]" => true } }
-
# }
-
# }
-
end
-
-
1
view :edit_nests, cache: :never do
-
frame do
-
with_nest_mode :edit do
-
multi_card_edit
-
end
-
end
-
end
-
-
# FIXME: - view can recurse. temporarily turned off
-
#
-
# view :edit_nest_rules, cache: :never do
-
# return ""#
-
# view = args[:rule_view] || :field_related_rules
-
# frame do
-
# # with_nest_mode :edit do
-
# nested_fields.map do |name, _options|
-
# nest Card.fetch(name.to_name.trait(:self)),
-
# view: :titled, title: name, rule_view: view,
-
# hide: :set_label, show: :rule_navbar
-
# end
-
# end
-
# end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/editing.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Editor)
-
#
-
1
module Editor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/editor.rb"; end
-
-
1
Self::InputOptions.add_to_basket :options, "text area"
-
1
Self::InputOptions.add_to_basket :options, "text field"
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
14
voo.input_type.present? ? voo.input_type : input_type_from_rule
-
end
-
-
1
def input_type_from_rule
-
14
card.rule(:input_type)&.gsub(/[\[\]]/, "")&.tr(" ", "_")
-
end
-
-
1
def input_method input_type
-
27
"#{input_type}_input"
-
end
-
-
# core view of card is input
-
1
def input_defined_by_card
-
7
with_card input_type do |input_card|
-
nest input_card, view: :core
-
end
-
end
-
-
# move somewhere more accessible?
-
1
def with_card mark
-
7
return nil unless (card = Card[mark])
-
-
yield card
-
rescue Card::Error::CodenameNotFound
-
nil
-
end
-
-
1
view :input, unknown: true do
-
20
try(input_method(input_type)) ||
-
input_defined_by_card ||
-
send(input_method(default_input_type))
-
end
-
-
1
def default_input_type
-
7
:rich_text
-
end
-
-
1
def rich_text_input
-
7
send "#{Cardio.config.rich_text_editor || :text_area}_editor_input"
-
end
-
-
1
def text_area_input
-
text_area :content, rows: 5, class: "d0-card-content",
-
"data-card-type-code" => card.type_code
-
end
-
-
1
def text_field_input
-
text_field :content, class: classy("d0-card-content")
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Form)
-
#
-
1
module Form;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/form.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# FIELDSET VIEWS
-
-
# sometimes multiple card formgroups, sometimes just one
-
1
view :content_formgroups, cache: :never do
-
20
wrap_with :fieldset, edit_slot, class: classy("card-editor", "editor")
-
end
-
-
1
view :name_formgroup do
-
3
formgroup "Name", input: "name", help: false do
-
3
raw name_field
-
end
-
end
-
-
# single card content formgroup, labeled with "Content"
-
1
view :content_formgroup, unknown: true, cache: :never do
-
16
wrap_content_formgroup { content_field }
-
end
-
-
1
view :edit_in_form, cache: :never, perms: :update, unknown: true do
-
reset_form
-
@in_multi_card_editor = true
-
edit_slot
-
end
-
-
1
view :conflict_tracker, cache: :never, unknown: true do
-
20
return unless card&.real?
-
-
1
card.last_action_id_before_edit = card.last_action_id
-
1
hidden_field :last_action_id_before_edit, class: "current_revision_id"
-
end
-
-
1
def wrap_content_formgroup
-
8
formgroup("Content", input: :content, help: false,
-
8
class: classy("card-editor")) { yield }
-
end
-
-
1
def button_formgroup
-
8
wrap_with :div, class: classy("form-group") do
-
8
wrap_with :div, yield
-
end
-
end
-
-
1
def name_field
-
# value needed because otherwise gets wrong value if there are updates
-
3
text_field :name, value: card.name, autocomplete: "off"
-
end
-
-
1
def content_field
-
20
with_nest_mode :normal do
-
# by changing nest mode to normal, we ensure that editors (eg image
-
# previews) can render core views.
-
20
output [_render_conflict_tracker, _render_input]
-
end
-
end
-
-
# SAMPLE editor view for override
-
# view :input do
-
# text_area :content, rows: 5, class: "d0-card-content"
-
# end
-
-
1
def edit_slot
-
case
-
20
when inline_nests_editor? then _render_core
-
when multi_card_editor? then multi_card_edit(true)
-
when in_multi_card_editor? then editor_in_multi_card
-
20
else single_card_edit_field
-
end
-
end
-
-
# test: render nests within a normal rendering of the card's content?
-
# (as opposed to a standardized form)
-
1
def inline_nests_editor?
-
20
voo.input_type == :inline_nests
-
end
-
-
# test: are we opening a new multi-card form?
-
1
def multi_card_editor?
-
20
voo.structure || voo.edit_structure || # structure configured in voo
-
card.structure || # structure in card rule
-
edit_fields? # list of fields in card rule
-
end
-
-
# override and return true to optimize
-
1
def edit_fields?
-
20
edit_fields.present?
-
end
-
-
# test: are we already within a multi-card form?
-
1
def in_multi_card_editor?
-
20
@in_multi_card_editor.present?
-
end
-
-
1
def single_card_edit_field
-
20
if voo.show?(:type_formgroup) || voo.show?(:name_formgroup)
-
8
_render_content_formgroup # use formgroup for consistency
-
else
-
24
editor_wrap(:content) { content_field }
-
end
-
end
-
-
1
def editor_in_multi_card
-
add_junction_class
-
formgroup render_title,
-
input: "content", help: true, class: classy("card-editor") do
-
[content_field, (form.hidden_field(:type_id) if card.new_card?)]
-
end
-
end
-
-
1
def multi_card_edit fields_only=false
-
field_configs = edit_field_configs fields_only
-
return structure_link if field_configs.empty?
-
-
field_configs.map do |name, options|
-
nest name, options || {}
-
end.join "\n"
-
end
-
-
1
def structure_link
-
# LOCALIZE
-
structured = link_to_card card.structure_rule_card, "structured"
-
"<label>Content</label>"\
-
"<p><em>Uneditable; content is #{structured} without nests</em></p>"
-
end
-
-
# @param [Hash|Array] fields either an array with field names and/or field
-
# cards or a hash with the fields as keys and a hash with nest options as
-
# values
-
1
def process_edit_fields fields
-
fields.map do |field, opts|
-
field_nest field, opts
-
end.join "\n"
-
end
-
###
-
-
# If you use subfield cards to render a form for a new card
-
# then the subfield cards should be created on the new card not the existing
-
# card that build the form
-
-
1
def form
-
42
@form ||= inherit(:form) || new_form
-
end
-
-
1
def new_form
-
13
@form_root = true unless parent&.form_root
-
13
instantiate_builder(form_prefix, card, {})
-
end
-
-
1
def reset_form
-
@form = new_form
-
end
-
-
1
def form_prefix
-
case
-
14
when explicit_form_prefix then explicit_form_prefix # configured
-
14
when simple_form? then "card" # simple form
-
when parent.card.name == card.name then parent.form_prefix # card nests self
-
else edit_in_form_prefix
-
end
-
end
-
-
1
def simple_form?
-
14
form_root? || !form_root || !parent
-
end
-
-
1
def edit_in_form_prefix
-
"#{parent.form_prefix}[subcards][#{card.name.from form_context.card.name}]"
-
end
-
-
1
def explicit_form_prefix
-
14
inherit :explicit_form_prefix
-
end
-
-
1
def form_context
-
form_root? || !form_root ? self : parent
-
end
-
-
1
def form_root?
-
14
@form_root == true
-
end
-
-
1
def form_root
-
15
return self if @form_root
-
-
15
parent ? parent.form_root : nil
-
end
-
-
1
def card_form action, opts={}
-
20
@form_root = true
-
20
hidden = hidden_form_tags action, opts
-
20
form_for card, card_form_opts(action, opts) do |cform|
-
20
@form = cform
-
20
hidden + output(yield(cform))
-
end
-
end
-
-
1
def hidden_form_tags _action, opts
-
20
success = opts.delete :success
-
20
success_tags success
-
end
-
-
# @param action [Symbol] :create or :update
-
# @param opts [Hash] html options
-
# @option opts [Boolean] :redirect (false) if true form is no "slotter"
-
1
def card_form_opts action, opts={}
-
20
url, action = card_form_url_and_action action
-
20
html_opts = card_form_html_opts action, opts
-
20
form_opts = { url: url, html: html_opts }
-
20
form_opts[:remote] = true unless html_opts.delete(:redirect)
-
20
form_opts
-
end
-
-
1
def card_form_html_opts action, opts={}
-
20
add_class opts, "card-form"
-
20
add_class opts, "slotter" unless opts[:redirect] || opts[:no_slotter]
-
20
add_class opts, "autosave" if action == :update
-
20
opts
-
end
-
-
1
def card_form_url_and_action action
-
20
case action
-
20
when Symbol then [path(action: action), action]
-
when Hash then [path(action), action[:action]]
-
# for when non-action path args are required
-
else
-
raise Card::Error, "unsupported #card_form_url action: #{action}"
-
end
-
end
-
-
1
def editor_wrap type=nil
-
30
html_class = "editor"
-
30
html_class << " #{type}-editor" if type
-
30
wrap_with :div, class: html_class do
-
30
yield
-
end
-
end
-
-
# FIELD VIEWS
-
-
1
def add_junction_class
-
return unless card.name.junction?
-
-
class_up "card-editor", "RIGHT-#{card.name.tag_name.safe_key}"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/form.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (FormButtons)
-
#
-
1
module FormButtons;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/form_buttons.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def standard_submit_button
-
output [standard_save_button, standard_save_and_close_button]
-
end
-
-
1
def standard_save_button opts={}
-
return if voo&.hide?(:save_button)
-
add_class opts, "submit-button btn-sm mr-3 _update-history-pills"
-
opts[:text] ||= "Save"
-
opts["data-cy"] = "save"
-
submit_button opts
-
end
-
-
# @param opts [Hash]
-
# @option close [:modal, :overlay]
-
#
-
1
def standard_save_and_close_button opts={}
-
close = opts.delete(:close) || :modal
-
text = opts[:text] || "Save and Close"
-
add_class opts, "submit-button btn-sm mr-3 _close-on-success"
-
add_class opts, "_update-origin" unless opts[:no_origin_update]
-
opts.reverse_merge! text: text, "data-cy": "submit-#{close}"
-
-
submit_button opts
-
end
-
-
1
def standard_cancel_button args={}
-
8
args.reverse_merge! class: "cancel-button ml-4", href: path, "data-cy": "cancel"
-
8
cancel_button args
-
end
-
-
1
def modal_cancel_button
-
modal_close_button "Cancel", situation: "secondary", class: "btn-sm cancel-button"
-
end
-
-
1
def edit_cancel_button
-
modal_cancel_button
-
end
-
-
1
def new_cancel_button
-
voo.show?(:cancel_button) && modal_cancel_button
-
end
-
-
1
def delete_button opts={}
-
link_to "Delete", delete_button_opts(opts)
-
end
-
-
1
def delete_button_opts opts={}
-
add_class opts, "slotter btn btn-outline-danger ml-auto btn-sm"
-
opts["data-confirm"] = delete_confirm opts
-
opts[:path] = { action: :delete }
-
opts[:path][:success] = delete_success(opts) unless opts.delete(:no_success)
-
opts[:remote] = true
-
opts
-
end
-
-
1
def delete_confirm opts
-
opts.delete(:confirm) || "Are you sure you want to delete #{safe_name}?"
-
end
-
-
1
def delete_success opts
-
opts.delete(:success) || (main? ? "REDIRECT: *previous" : { view: :just_deleted })
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/form_buttons.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (FormElements)
-
#
-
1
module FormElements;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/form_elements.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def success_tags opts
-
20
return "" unless opts.present?
-
-
20
hidden_tags success: opts
-
end
-
-
# convert hash into a collection of hidden tags
-
1
def hidden_tags hash, base=nil
-
56
hash ||= {}
-
56
hash.inject("") do |result, (key, val)|
-
56
new_base = base ? "#{base}[#{key}]" : key
-
56
result + process_hidden_value(val, new_base)
-
end
-
end
-
-
1
def process_hidden_value val, base
-
56
case val
-
when Hash
-
24
hidden_tags val, base
-
when Array
-
base += "[]"
-
val.map do |v|
-
hidden_field_tag base, v
-
end.join
-
else
-
32
hidden_field_tag base, val
-
end
-
end
-
-
FIELD_HELPERS =
-
%w[
-
1
hidden_field color_field date_field datetime_field datetime_local_field
-
email_field month_field number_field password_field phone_field
-
range_field search_field telephone_field text_area text_field time_field
-
url_field week_field file_field label check_box radio_button
-
].freeze
-
-
1
FIELD_HELPERS.each do |method_name|
-
22
define_method(method_name) do |*args|
-
form.send(method_name, *args)
-
end
-
end
-
-
1
def submit_button args={}
-
8
text = args.delete(:text) || "Submit"
-
8
args.reverse_merge! situation: "primary", data: {}
-
8
args[:data][:disable_with] ||= args.delete(:disable_with) || "Submitting"
-
8
button_tag text, args
-
end
-
-
# redirect to *previous if no :href is given
-
1
def cancel_button args={}
-
8
return unless voo.show? :cancel_button
-
8
text = args.delete(:text) || "Cancel"
-
8
add_class args, "btn btn-#{args.delete(:situation) || 'secondary'}"
-
8
add_class args, cancel_strategy(args[:redirect], args[:href])
-
8
args[:href] ||= path_to_previous
-
8
args["data-remote"] = true
-
8
link_to text, args
-
end
-
-
1
def cancel_strategy redirect, href
-
8
redirect = href.blank? if redirect.nil?
-
8
redirect ? "redirecter" : "slotter"
-
end
-
-
1
def path_to_previous
-
8
path mark: "*previous"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/form_elements.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Formgroup)
-
#
-
1
module Formgroup;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/formgroup.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# a formgroup has a label, an input and help text
-
1
def formgroup title, opts={}, &block
-
18
wrap_with :div, formgroup_div_args(opts[:class]) do
-
18
formgroup_body title, opts, &block
-
end
-
end
-
-
1
def formgroup_body title, opts, &block
-
18
label = formgroup_label opts[:input], title
-
18
editor_body = editor_wrap opts[:input], &block
-
18
help_text = formgroup_help_text opts[:help]
-
18
"#{label}<div>#{help_text} #{editor_body}</div>"
-
end
-
-
1
def formgroup_label input, title
-
18
return if voo&.hide?(:title) || title.blank?
-
-
18
label_type = input || :content
-
18
form.label label_type, title
-
end
-
-
1
def formgroup_div_args html_class
-
18
div_args = { class: ["form-group", html_class].compact.join(" ") }
-
18
div_args[:card_id] = card.id if card.real?
-
18
div_args[:card_name] = h card.name if card.name.present?
-
18
div_args
-
end
-
-
1
def formgroup_help_text text=nil
-
18
return "" if text == false
-
-
class_up "help-text", "help-block"
-
voo.help = text if voo && text.to_s != "true"
-
_render_help
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/formgroup.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (New)
-
#
-
1
module New;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/new.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :new, perms: :create, unknown: true, cache: :never do
-
8
new_view_frame_and_form new_form_opts
-
end
-
-
1
view :new_content_form, wrap: :slot, unknown: true, cache: :never do
-
with_nest_mode :edit do
-
create_form
-
end
-
end
-
-
1
view :new_in_modal, perms: :create, unknown: true, cache: :never,
-
wrap: { modal: { footer: "", size: :edit_modal_size,
-
title: :new_in_modal_title,
-
menu: :new_modal_menu } } do
-
_render_new_content_form
-
end
-
-
1
def create_form
-
form_opts = new_in_modal_form_opts.reverse_merge(success: new_in_modal_success)
-
buttons = form_opts.delete(:buttons) || _render_new_buttons
-
-
voo.title ||= new_view_title if new_name_prompt?
-
voo.show :help
-
card_form(:create, form_opts) do
-
create_form_with_alert_guide buttons
-
end
-
end
-
-
1
def new_modal_size
-
:large
-
end
-
-
1
def new_modal_menu
-
wrap_with_modal_menu do
-
[close_modal_window, render_bridge_link]
-
end
-
end
-
-
1
def new_view_frame_and_form form_opts={}
-
8
buttons = form_opts.delete(:buttons) || _render_new_buttons
-
8
form_opts = form_opts.reverse_merge(success: new_success)
-
-
8
with_nest_mode :edit do
-
8
voo.title ||= new_view_title if new_name_prompt?
-
8
voo.show :help
-
8
frame_and_form :create, form_opts do
-
8
create_form_with_alert_guide buttons
-
end
-
end
-
end
-
-
1
def create_form_with_alert_guide buttons
-
8
wrap_with :div, class: "d-flex justify-content-between" do
-
8
[(wrap_with(:div, class: "w-100") do
-
[
-
8
new_view_hidden,
-
new_view_name,
-
new_view_type,
-
_render_content_formgroups,
-
buttons
-
]
-
end),
-
8
(alert_guide if voo.show?(:guide))]
-
end
-
end
-
-
1
def new_view_hidden; end
-
-
1
def new_in_modal_form_opts
-
{ "data-slot-selector": "modal-origin", "data-slot-error-selector": ".card-slot",
-
buttons: _render_new_in_modal_buttons }
-
end
-
-
1
def new_form_opts
-
8
{ "main-success" => "REDIRECT" }
-
end
-
-
1
def new_view_title
-
3
output(
-
"New",
-
3
(card.type_name unless card.type_id == Card.default_type_id)
-
)
-
end
-
-
1
def new_in_modal_title
-
new_name_prompt? ? new_view_title : render_title
-
end
-
-
1
def new_success
-
8
card.rule(:thanks) || "_self"
-
end
-
-
1
def new_in_modal_success; end
-
-
# NAME HANDLING
-
-
1
def new_view_name
-
8
if new_name_prompt?
-
3
new_name_formgroup
-
5
elsif !autoname?
-
5
hidden_field_tag "card[name]", card.name
-
end
-
end
-
-
1
def new_name_formgroup
-
3
output _render_name_formgroup,
-
hidden_field_tag("name_prompt", true)
-
end
-
-
1
def new_name_prompt?
-
16
voo.visible? :name_formgroup do
-
8
needs_name? || params[:name_prompt]
-
end
-
end
-
-
1
def autoname?
-
8
@autoname.nil? ? (@autoname = card.rule_card :autoname).present? : @autoname
-
end
-
-
1
def needs_name?
-
8
card.name.blank? && !autoname?
-
end
-
-
# TYPE HANDLING
-
-
1
def new_view_type
-
8
if new_type_prompt?
-
7
_render_new_type_formgroup
-
else
-
1
hidden_field_tag "card[type_id]", card.type_id
-
end
-
end
-
-
1
def new_type_prompt?
-
8
voo.visible? :new_type_formgroup do
-
8
!new_type_preset? && new_type_prompt_context? && new_type_permitted?
-
end
-
end
-
-
1
def new_type_preset?
-
8
params[:type] || voo.type
-
end
-
-
1
def new_type_prompt_context?
-
7
main? || card.simple? || card.is_template?
-
end
-
-
1
def new_type_permitted?
-
7
Card.new(type_id: card.type_id).ok? :create
-
end
-
-
1
view :new_type_formgroup do
-
7
wrap_type_formgroup do
-
7
type_field class: "type-field live-type-field",
-
href: path(view: :new),
-
"data-remote" => true
-
end
-
end
-
-
1
view :new_buttons do
-
8
button_formgroup do
-
8
[standard_create_button, standard_cancel_button(cancel_button_new_args)]
-
end
-
end
-
-
1
view :new_in_modal_buttons do
-
button_formgroup do
-
wrap_with "div", class: "d-flex" do
-
[standard_save_and_close_button(text: "Submit"), modal_cancel_button]
-
end
-
end
-
end
-
-
# path to redirect to after canceling a new form
-
1
def cancel_button_new_args
-
href = case
-
16
when main? then path_to_previous
-
when voo&.home_view then path(view: voo.home_view)
-
else path(view: :unknown)
-
end
-
8
{ href: href }
-
end
-
-
1
def standard_create_button
-
8
submit_button class: "submit-button create-submit-button"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/new.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (OverlayGuide)
-
#
-
1
module OverlayGuide;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/overlay_guide.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :overlay_guide,
-
cache: :never, unknown: true, template: :haml,
-
wrap: { slot: { class: "_overlay d0-card-overlay card nodblclick" } } do
-
# TODO: use a common template for this and the nest editor
-
# (the common thing is that they both are an overlay of the bridge sidebar)
-
# and maybe make it look more like the overlay on the left with the same close icon
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/overlay_guide.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (TemplateNest)
-
#
-
1
module TemplateNest;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/template_nest.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :template_nest, cache: :never, unknown: true do
-
return "" unless voo.nest_name
-
-
if voo.nest_name.to_name.field_only?
-
with_nest_mode :normal do
-
nest template_link_set_name, view: :template_link
-
end
-
else
-
"{{#{voo.nest_syntax}}}"
-
end
-
end
-
-
1
def template_link_set_name
-
name = voo.nest_name.to_name
-
if name.absolute?
-
name.trait_name :self
-
else
-
template_link_set_name_for_relative_name name
-
end
-
end
-
-
1
def template_link_set_name_for_relative_name name
-
name = name.stripped.gsub(/^\+/, "")
-
-
if (type = on_type_set)
-
[type, name].to_name.trait_name :type_plus_right
-
else
-
name.to_name.trait_name :right
-
end
-
end
-
-
1
def on_type_set
-
return unless
-
(tmpl_set_name = parent.card.name.trunk_name) &&
-
(tmpl_set_class_name = tmpl_set_name.tag_name) &&
-
(tmpl_set_class_card = Card[tmpl_set_class_name]) &&
-
(tmpl_set_class_card.codename == :type)
-
-
tmpl_set_name.left_name
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/all/template_nest.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "List" cards
-
#
-
1
module List;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/type/list.rb"; end
-
1
def input_type_content_options
-
["multiselect", "checkbox", "autocompleted list", "filtered list"]
-
end
-
-
1
def show_content_options?
-
true
-
end
-
-
1
def show_input_type?
-
true
-
end
-
-
1
def field_settings
-
%i[default help input_type content_options content_option_view]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/type/list.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "PlainText" cards
-
#
-
1
module PlainText;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/type/plain_text.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type_content_options
-
["text area", "text field", "ace editor"]
-
end
-
end
-
-
1
def field_settings
-
%i[default help input_type]
-
end
-
-
1
def show_input_type?
-
true
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/type/plain_text.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Pointer" cards
-
#
-
1
module Pointer;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-edit/set/type/pointer.rb"; end
-
1
def show_content_options?
-
true
-
end
-
-
1
def show_input_type?
-
true
-
end
-
-
1
def input_type_content_options
-
%w[select radio autocomplete]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-edit/set/type/pointer.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (AceEditor)
-
#
-
1
module AceEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/all/ace_editor.rb"; end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def ace_editor_input
-
text_area :content, rows: 5,
-
class: "d0-card-content ace-editor-textarea",
-
"data-ace-mode" => ace_mode
-
end
-
-
1
def ace_mode
-
:html
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/all/ace_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Ace"
-
#
-
1
module Ace;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/self/ace.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def raw_help_text
-
"Configure [[https://ace.c9.io/|ace]], "\
-
"Decko's default code editor, using these available "\
-
"[[https://github.com/ajaxorg/ace/wiki/Configuring-Ace|options]]."
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/self/ace.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptAce"
-
#
-
1
module ScriptAce;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/self/script_ace.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptLibraries.add_item :script_ace
-
1
Self::InputOptions.add_to_basket :options, "ace editor"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/self/script_ace.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptAceConfig"
-
#
-
1
module ScriptAceConfig;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/self/script_ace_config.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptEditors.add_item :script_ace_config
-
1
All::Head::HtmlFormat.add_to_basket :mod_js_config, [:ace, "setAceConfig"]
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-ace_editor/set/self/script_ace_config.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Media)
-
#
-
1
module Media;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/abstract/media.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def image_card
-
@image_card ||= card.fetch(:image, new: {})
-
end
-
-
1
def text_with_image opts={}
-
class_up "media-left", "m-2"
-
@image_card = Card.cardish(opts[:image]) if opts[:image]
-
haml :media_snippet, normalized_text_with_image_opts(opts)
-
end
-
-
1
private
-
-
1
def normalized_text_with_image_opts opts
-
opts.reverse_merge! title: _render_title, text: "", size: voo.size, media_opts: {}
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/abstract/media.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Bar)
-
#
-
1
module Bar;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/all/bar.rb"; end
-
1
include_set Abstract::BsBadge
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
setting :bar_cols
-
1
setting :info_bar_cols
-
-
1
view :info_bar do
-
render_bar show: :bar_middle
-
end
-
-
1
before :bar do
-
32
class_up "bar", card.safe_set_keys
-
32
voo.hide! :bar_collapse_link
-
32
voo.hide :edit_link, :full_page_link, :bridge_link
-
end
-
-
1
view :bar, unknown: :unknown_bar do
-
25
voo.hide :bar_middle
-
25
voo.hide :bar_bottom # needed for toggle
-
25
class_up_bar_sides(voo.show?(:bar_middle))
-
# note: above cannot be in `before`, because before blocks run before viz processing
-
50
wrap { haml :bar }
-
end
-
-
1
bar_cols 9, 3
-
1
info_bar_cols 5, 4, 3
-
-
1
view :unknown_bar, unknown: true do
-
2
voo.hide! :bar_middle, :bar_bottom, :bar_nav
-
4
wrap { haml :bar }
-
end
-
-
1
before :expanded_bar do
-
class_up "bar", card.safe_set_keys
-
voo.hide! :bar_expand_link
-
end
-
-
1
view :expanded_bar do
-
class_up_bar_sides(false)
-
wrap { haml :expanded_bar }
-
end
-
-
1
def class_up_bar_sides middle
-
25
class_up_cols %w[bar-left bar-right], bar_cols
-
25
class_up_cols %w[bar-left bar-middle bar-right], info_bar_cols, "md" if middle
-
end
-
-
1
def class_up_cols classes, cols, context=nil
-
25
classes.each_with_index do |cls, i|
-
50
class_up cls, ["col", context, cols[i]].compact.join("-")
-
end
-
end
-
-
1
view :bar_left do
-
25
bar_title
-
end
-
-
1
def bar_title
-
25
return render_missing if card.unknown?
-
-
25
if voo.show?(:toggle)
-
25
link_to_view bar_title_toggle_view, render_title
-
else
-
render_title
-
end
-
end
-
-
1
def bar_title_toggle_view
-
25
voo.show?(:bar_bottom) ? :bar : :expanded_bar
-
end
-
-
1
view :bar_right, unknown: :blank do
-
25
[(render(:short_content) unless voo.show?(:bar_middle)),
-
render(:edit_button, optional: :hide)]
-
end
-
-
1
view :bar_middle, unknown: :blank do
-
render :short_content
-
end
-
-
1
view :bar_bottom do
-
render(nest_mode == :edit ? :edit : :core)
-
end
-
-
1
view :bar_nav, unknown: true, wrap: { div: { class: "bar-nav" } } do
-
5
[render_bar_expand_link,
-
render_bar_collapse_link,
-
render_full_page_link,
-
render_edit_link,
-
render_bridge_link]
-
end
-
-
1
view :bar_expand_link, unknown: true do
-
5
link_to_view :expanded_bar, icon_tag(:keyboard_arrow_down)
-
end
-
-
1
view :bar_collapse_link, unknown: true do
-
link_to_view :bar, icon_tag(:keyboard_arrow_up)
-
end
-
-
1
view :edit_button do
-
view = voo.edit == :inline ? :edit_inline : :edit
-
link_to_view view, "Edit", class: "btn btn-sm btn-outline-primary mr-2"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/all/bar.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Box)
-
#
-
1
module Box;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/all/box.rb"; end
-
1
view :box, template: :haml do
-
voo.hide :menu
-
end
-
-
1
view :box_top do
-
render_title_link
-
end
-
-
1
view :box_middle do
-
_render_content
-
end
-
-
1
view :box_bottom do
-
[_render_creator_credit,
-
_render_updated_by]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/all/box.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleMedia"
-
#
-
1
module StyleMedia;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/self/style_media.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::StyleMods.add_item :style_media
-
-
1
def source_files
-
2
scss_files [:image_box]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/self/style_media.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Image" cards
-
#
-
1
module Image;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/type/image.rb"; end
-
IMAGE_BOX_SIZE_MAP = {
-
1
icon: :icon, small: :small, medium: :small, large: :medium, xlarge: :medium
-
}.freeze
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :boxed, unknown: true do
-
image_box { |size| render_core size: size }
-
end
-
-
1
view :boxed_link, unknown: true do
-
image_box { |size| link_to_card image_box_link_target, render_core(size: size) }
-
end
-
-
1
def image_box
-
voo.size ||= :medium
-
wrap_with :div, title: image_box_title, class: "image-box #{voo.size}" do
-
yield image_box_size
-
end
-
end
-
-
## METHODS FOR OVERRIDE
-
-
1
def image_box_size
-
IMAGE_BOX_SIZE_MAP[voo.size.to_sym] || :medium
-
end
-
-
1
def image_box_card_name
-
card.name.junction? ? card.name.left : card.name
-
end
-
-
1
def image_box_link_target
-
image_box_card_name
-
end
-
-
1
def image_box_title
-
voo.title || image_box_card_name
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bar_and_box/set/type/image.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (BootstrapCodeFile)
-
#
-
1
module BootstrapCodeFile;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/abstract/bootstrap_code_file.rb"; end
-
-
1
def self.included host_class
-
3
host_class.include_set Abstract::CodeFile
-
3
host_class.include OverrideCodeFile
-
end
-
-
1
module OverrideCodeFile
-
1
def content
-
3
stylesheets.join "\n"
-
end
-
-
1
def stylesheets
-
3
load_stylesheets unless @stylesheets
-
3
@stylesheets
-
end
-
-
1
def add_bs_subdir sub_dir
-
2
Dir.glob("#{bootstrap_path}/#{sub_dir}/*.scss").each do |path|
-
45
load_from_path path
-
end
-
end
-
-
1
def mod_path
-
35
mod_root :bootstrap
-
end
-
-
1
def bootstrap_path
-
34
"#{mod_path}/vendor/bootstrap/scss"
-
end
-
-
1
def add_stylesheet filename, type: :scss
-
load_from_path "#{mod_path}/lib/stylesheets/#{filename}.#{type}"
-
end
-
-
1
def add_stylesheet_file path
-
1
load_from_path File.join(mod_path, path)
-
end
-
-
1
def add_bs_stylesheet filename, type: :scss, subdir: nil
-
32
path = File.join(*[bootstrap_path, subdir, "_#{filename}.#{type}"].compact)
-
32
load_from_path path
-
end
-
-
1
def load_from_path path
-
78
@stylesheets ||= []
-
78
Rails.logger.info "reading file: #{path}"
-
78
@stylesheets << File.read(path)
-
end
-
-
1
def source_changed _since:
-
false
-
end
-
-
1
def existing_source_paths
-
3
[]
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/abstract/bootstrap_code_file.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (BootswatchTheme)
-
#
-
# Bootswatch themes are free themes for bootstrap available at https://bootswatch.com/.
-
# For every bootswatch theme we have one card of card type "bootswatch skin".
-
# They all have codenames following the pattern "#{theme_name}_skin".
-
#
-
# The original bootswatch theme is build from two files, `_variables.scss` and
-
# `_bootswatch.scss`. The original bootstrap scss has to be put between those two.
-
# `_variables.scss` overrides bootstrap variables, `_bootswatch.scss` overrides
-
# bootstrap css (variables are defined with `!default` hence only the first appearance
-
# has an effect, for css the last appearance counts)
-
#
-
# The content of a bootswatch theme card consists of four parts:
-
# * pre_variables: hard-coded theme independent stuff
-
# and bootstrap functions to make them available in the variables part
-
# * variables: the content from `_variables.scss`,
-
# * post_variables: the bootstrap css and libraries like select2 and
-
# bootstrap-colorpicker that depend on the theme
-
# * stylesheets: the content from `_bootswatch.scss` and custom styles
-
#
-
# For the original bootswatch themes all those parts are hard-coded and the content
-
1
module BootswatchTheme;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/abstract/bootswatch_theme.rb"; end
-
# is taken from files.
-
# The bootswatch theme content is taken directly from the files in the bootswatch
-
# submodule. For the rest we use code file cards.
-
# Cards of type "customized bootswatch skin" have the same structure but make the variables
-
# and stylesheets part editable.
-
#
-
# Bootswatch theme cards are machine cards for the following reason.
-
# Machine cards usually store all involved input cards of all nested levels in
-
# there +*machine_input pointer. All those input cards
-
# are processed separately and the result is joined to build the machine output.
-
# That's a problem for this card when it's used as input.
-
# A lot of the items depend on the variables scss and can't
-
# be processed independently. Therefore we return only self as item card and join
-
# the content of all the item cards in the content of the bootswatch theme card.
-
# But then this card has to forward updates of its items to the machine cards it provides
-
# input for.
-
# To do that it is a machine itself and stores the generated machine output as its
-
# content which will trigger the updates of other machines that use this card.
-
-
1
include_set Abstract::Machine
-
1
include_set Type::Scss
-
1
include_set Abstract::CodeFile
-
1
include_set Abstract::SkinBox
-
-
1
CONTENT_PARTS = %i[pre_variables variables post_variables stylesheets].freeze
-
-
1
PRE_VARIABLES_CARD_NAMES = %i[
-
style_jquery_ui_smoothness
-
bootstrap_functions
-
].freeze
-
-
1
POST_VARIABLES_CARD_NAMES = %i[
-
bootstrap_core
-
style_cards
-
style_bootstrap_cards
-
style_libraries
-
style_mods
-
].freeze
-
-
# @return [Array<Card::Name,String>]
-
1
def variables_card_names
-
1
[]
-
end
-
-
# @return [Array<Card::Name,String>]
-
1
def stylesheets_card_names
-
1
[]
-
end
-
-
# reject cards that don't contribute directly to the content like skin or pointer cards
-
1
def engine_input
-
extended_input_cards.select { |ca| ca.type_id.in? [Card::ScssID, Card::CssID] }
-
end
-
-
# Don't create "+*machine output" file card
-
# instead save the the output as the card's content is
-
1
def after_engine output
-
Card::Auth.as_bot { update! db_content: output }
-
end
-
-
# needed to make the refresh_script_and_style method work with these cards
-
1
def source_files
-
extended_input_cards.map do |i_card|
-
i_card.try(:source_files)
-
end.flatten.compact
-
end
-
-
# needed to make the refresh_script_and_style method work with these cards
-
1
def existing_source_paths
-
1
extended_input_cards.map do |i_card|
-
12
i_card.try(:existing_source_paths)
-
end.flatten.compact
-
end
-
-
1
def extended_input_cards
-
1
input_names.map do |n|
-
7
Card.fetch(n).extended_item_cards
-
end.flatten.compact
-
end
-
-
1
def content
-
1
CONTENT_PARTS.map do |n|
-
4
send "#{n}_content"
-
end.join "\n"
-
end
-
-
1
def pre_variables_content
-
1
load_content(*PRE_VARIABLES_CARD_NAMES)
-
end
-
-
1
def variables_content
-
load_content variables_card_names
-
end
-
-
1
def post_variables_content
-
1
load_content(*POST_VARIABLES_CARD_NAMES)
-
end
-
-
1
def stylesheets_content
-
load_content stylesheets_card_names
-
end
-
-
1
def input_names _args={}
-
1
(PRE_VARIABLES_CARD_NAMES + variables_card_names +
-
POST_VARIABLES_CARD_NAMES + stylesheets_card_names).compact.map do |n|
-
7
Card.fetch_name(n)
-
end.compact
-
end
-
-
1
def item_names _args={}
-
[]
-
end
-
-
1
def item_cards _args={}
-
4
[self]
-
end
-
-
1
def load_content *names
-
9
cards = names.flatten.map { |n| Card.fetch(n)&.extended_item_cards }
-
2
cards.flatten.compact.map(&:content).join "\n"
-
end
-
-
1
def scss_from_theme_file file
-
2
return "" unless (path = ::File.join(source_dir, "_#{file}.scss")) &&
-
::File.exist?(path)
-
2
::File.read path
-
end
-
-
1
def theme_name
-
1
/^(.+)_skin$/.match(codename)&.capture(0) ||
-
/^(.+)[ _][sS]kin/.match(name)&.capture(0)&.downcase
-
end
-
-
1
def source_dir
-
2
@source_dir ||= File.expand_path(
-
"#{mod_root :bootstrap}/vendor/bootswatch/dist/#{theme_name}", __FILE__
-
)
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/abstract/bootswatch_theme.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module BootswatchTheme;
-
# Set: Abstract (BootswatchTheme, HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/abstract/bootswatch_theme/html_views.rb"; end
-
1
include_set Abstract::Media
-
1
include_set Abstract::BsBadge
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
before :box do
-
voo.show! :customize_button, :box_middle
-
end
-
-
1
view :one_line_content do
-
""
-
end
-
-
1
view :bar_left do
-
class_up "card-title", "my-0 ml-2"
-
class_up "media-left", "m-0"
-
text_with_image size: :medium, title: "", text: _render_title,
-
media_opts: { class: "align-items-center" }
-
# field_nest(:image, view: :core) + wrap_with(:h4, render(:title))
-
end
-
-
1
view :bar_right do
-
customize_button text: "Customize"
-
end
-
-
1
view :bar_bottom do
-
wrap_with :code do
-
render_core
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/abstract/bootswatch_theme/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Accordion)
-
#
-
1
module Accordion;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/accordion.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def accordion_group list, collapse_id=nil, args={}
-
collapse_id ||= card.name.safe_key
-
accordions = ""
-
index = 1
-
case list
-
when Array then accordions = list.join
-
when String then accordions = list
-
else
-
list.each_pair do |title, content|
-
accordions << accordion(title, content, "#{collapse_id}-#{index}")
-
index += 1
-
end
-
end
-
add_class args, "act-accordion-group w-100"
-
wrap_with :div, class: args[:class], id: "accordion-#{collapse_id}",
-
role: "tablist", "aria-multiselectable" => "true" do
-
accordions
-
end
-
end
-
-
1
def accordion title, content, collapse_id=card.name.safe_key
-
accordion_content =
-
case content
-
when Hash then accordion_group content, collapse_id
-
when Array then content.present? && list_group(content)
-
when String then content
-
end
-
<<-HTML.html_safe
-
<div class="card">
-
#{accordion_panel(title, accordion_content, collapse_id)}
-
</div>
-
HTML
-
end
-
-
1
def accordion_panel title, body, collapse_id, _panel_heading_link=false
-
if body
-
<<-HTML
-
<div class="card-header" role="tab" id="heading-#{collapse_id}">
-
<h5 class="mb-0">
-
<a data-toggle="collapse" data-parent="#accordion-#{collapse_id}" \
-
href="##{collapse_id}" aria-expanded="true" \
-
aria-controls="#{collapse_id}">
-
#{title}
-
</a>
-
</h5>
-
</div>
-
<div id="#{collapse_id}" class="collapse" \
-
role="tabpanel" aria-labelledby="heading-#{collapse_id}">
-
<div class="card-body">
-
#{body}
-
</div>
-
</div>
-
HTML
-
else
-
<<-HTML
-
<li class="list-group-item">
-
<h4 class="card-header">#{title}</h4>
-
</li>
-
HTML
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/accordion.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Dropdown)
-
#
-
1
module Dropdown;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/dropdown.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def dropdown_button name, items_or_opts={}, opts={}
-
items = block_given? ? yield : items_or_opts
-
opts = items_or_opts if block_given?
-
<<-HTML
-
<div class="btn-group #{opts[:extra_css_class]}" role="group">
-
<button class="btn btn-primary dropdown-toggle"
-
data-toggle="dropdown" title="#{name}" aria-expanded="false"
-
aria-haspopup="true">
-
#{icon_tag opts[:icon] if opts[:icon]} #{name}
-
<span class="caret"></span>
-
</button>
-
#{dropdown_list items, opts[:class], opts[:active]}
-
</div>
-
HTML
-
end
-
-
1
def split_button main_button, active_item
-
15
wrap_with :div, class: "btn-group" do
-
[
-
15
main_button,
-
split_button_toggle,
-
dropdown_list(yield, "dropdown-menu-right", active_item)
-
]
-
end
-
end
-
-
1
private
-
-
# @param items
-
# [String] plain html
-
# [Array<String, Array>] list of item names
-
# If an item is an array then the first element is used as header for a section.
-
# The second item has to be an array with the item names for that section.
-
# [Hash] key is used to identify active item, value is the item name.
-
# @param active specifies which item to highlight as active. If items are given as array
-
# it has to be the index of the active item. If items are given as hash it has to be
-
# the key of that item.
-
1
def dropdown_list items, extra_css_class=nil, active=nil
-
15
wrap_with :ul, class: "dropdown-menu #{extra_css_class}", role: "menu" do
-
list =
-
15
case items
-
when Array
-
15
dropdown_array_list items, active
-
when Hash
-
dropdown_hash_list items, active
-
else
-
[items]
-
end
-
15
list.flatten.compact.join "\n"
-
end
-
end
-
-
1
def dropdown_header text
-
12
content_tag(:h6, text, class: "dropdown-header")
-
end
-
-
1
def dropdown_hash_list items, active=nil
-
items.map { |key, item| dropdown_list_item item, key, active }
-
end
-
-
1
def dropdown_array_list items, active=nil
-
85
items.map.with_index { |item, i| dropdown_list_item item, i, active }
-
end
-
-
1
def dropdown_list_item item, active_test, active
-
58
return unless item
-
-
55
if item.is_a? Array
-
12
[dropdown_header(item.first), dropdown_array_list(item.second)]
-
else
-
43
"<li class='dropdown-item#{' active' if active_test == active}'>#{item}</li>"
-
end
-
end
-
-
1
def split_button_toggle
-
15
wrap_with(:a,
-
href: "#",
-
class: "nav-link pl-0 dropdown-toggle dropdown-toggle-split",
-
"data-toggle" => "dropdown",
-
"aria-haspopup" => "true",
-
"aria-expanded" => "false") do
-
15
'<span class="sr-only">Toggle Dropdown</span>'
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/dropdown.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Form)
-
#
-
1
module Form;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/form.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def button_tag content_or_options=nil, options={}, &block
-
8
bootstrapify_button(block_given? ? content_or_options : options)
-
8
super(content_or_options, options, &block)
-
end
-
-
1
def bootstrapify_button options
-
8
situation = options.delete(:situation) || "primary"
-
8
options[:class] = [options[:class], "btn", "btn-#{situation}"].compact * " "
-
end
-
-
1
def type_field args={}
-
7
args[:class] ||= ""
-
7
args[:class] += " form-control"
-
7
super(args)
-
end
-
-
1
def bootstrap_options options
-
24
options[:class] ||= ""
-
24
options[:class] += " form-control"
-
24
options
-
end
-
-
1
FIELD_HELPERS = %w[hidden_field color_field date_field datetime_field
-
datetime_local_field email_field month_field number_field
-
password_field phone_field range_field search_field
-
telephone_field text_area text_field time_field
-
url_field week_field file_field].freeze
-
-
1
FIELD_HELPERS.each do |method_name|
-
19
define_method(method_name) do |name, options={}|
-
24
form.send(method_name, name, bootstrap_options(options))
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/form.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Helper)
-
#
-
1
module Helper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/helper.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def button_link link_text, opts={}
-
btn_type = opts.delete(:btn_type) || "primary"
-
opts[:class] = [opts[:class], "btn btn-#{btn_type}"].compact.join " "
-
smart_link_to link_text, opts
-
end
-
-
1
def separator
-
'<li role="separator" class="divider"></li>'
-
end
-
-
1
def list_group content_or_options=nil, options={}
-
options = content_or_options if block_given?
-
content = block_given? ? yield : content_or_options
-
content = Array(content).map(&:to_s)
-
add_class options, "list-group"
-
options[:items] ||= {}
-
add_class options[:items], "list-group-item"
-
list_tag content, options
-
end
-
-
1
def list_tag content_or_options=nil, options={}
-
options = content_or_options if block_given?
-
content = block_given? ? yield : content_or_options
-
content = Array(content)
-
default_item_options = options.delete(:items) || {}
-
tag = options[:ordered] ? :ol : :ul
-
wrap_with tag, options do
-
content.map do |item|
-
i_content, i_opts = item
-
i_opts ||= default_item_options
-
wrap_with :li, i_content, i_opts
-
end
-
end
-
end
-
-
1
def badge_tag content, options={}
-
add_class options, "badge"
-
wrap_with :span, content, options
-
end
-
-
1
def popover_link text, title=nil, link_text=fa_icon("question-circle"), opts={}
-
link_to link_text, popover_opts(text, title, opts)
-
end
-
-
1
def popover_opts text, title, opts
-
6
add_class opts, "pl-1 text-muted-link"
-
6
opts.merge! path: "#", "data-toggle": "popover",
-
"data-trigger": :focus, "data-content": text
-
6
opts["data-title"] = title if title
-
6
opts
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/helper.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Icon)
-
#
-
1
module Icon;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/icon.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# same for all:
-
# :search,
-
ICON_MAP = {
-
1
material: {
-
plus: :add,
-
pencil: :edit,
-
trash: :delete,
-
wrench: :build,
-
new_window: :open_in_new,
-
history: :history,
-
triangle_left: :expand_less,
-
triangle_right: :expand_more,
-
flag: :flag,
-
option_horizontal: :more_horiz,
-
option_vertical: :more_vert,
-
pushpin: :pin_drop,
-
baby_formula: :device_hub,
-
log_out: :call_made,
-
log_in: :call_received,
-
explore: :explore,
-
remove: :close,
-
expand: :expand_more,
-
collapse_down: :expand_less,
-
globe: :public,
-
check_circle_o: nil,
-
commenting: :comment
-
},
-
font_awesome: {
-
option_horizontal: :ellipsis_h,
-
pushpin: "thumb-tack",
-
globe: :globe,
-
zoom_out: "search-minus",
-
close: :remove,
-
check_circle_o: "check-circle-o",
-
check_circe: "check-circle",
-
reorder: "align-justify",
-
commenting: :commenting
-
},
-
glyphicon: {
-
option_horizontal: "option-horizontal",
-
option_vertical: "option-vertical",
-
triangle_left: "triangle-left",
-
triangle_right: "triangle-right",
-
baby_formula: "baby-formula",
-
log_out: "log-out",
-
log_in: "log-in",
-
collapse_down: "collapse-down",
-
globe: :globe,
-
zoom_out: "zoom-out",
-
close: :remove,
-
new_window: "new-window",
-
history: :time,
-
check_circle_o: "ok-circle",
-
check_circle: "ok-sign",
-
reorder: "align-justify"
-
}
-
-
}.freeze
-
-
1
def icon_class library, icon
-
28
ICON_MAP[library][icon] || icon
-
end
-
-
1
def material_icon icon, opts={}
-
18
universal_icon_tag icon, :material, opts
-
end
-
-
1
def glyphicon icon, opts={}
-
universal_icon_tag icon, :glyphicon, opts
-
end
-
-
1
def fa_icon icon, opts={}
-
2
universal_icon_tag icon, :font_awesome, opts
-
end
-
-
1
def icon_tag icon, opts={}
-
8
opts = { class: opts } unless opts.is_a? Hash
-
8
library = opts.delete(:library) || default_icon_library
-
8
universal_icon_tag icon, library, opts
-
end
-
-
1
def universal_icon_tag icon, icon_library=default_icon_library, opts={}
-
28
return "" unless icon.present?
-
-
28
opts = { class: opts } unless opts.is_a? Hash
-
28
icon_method = "#{icon_library}_icon_tag"
-
28
send icon_method, icon, opts
-
end
-
-
1
def default_icon_library
-
8
:material
-
end
-
-
1
def glyphicon_icon_tag icon, opts={}
-
prepend_class opts, "glyphicon glyphicon-#{icon_class(:glyphicon, icon)}"
-
wrap_with :span, "", opts.merge("aria-hidden": true)
-
end
-
-
1
def font_awesome_icon_tag icon, opts={}
-
2
prepend_class opts, "fa fa-#{icon_class(:font_awesome, icon)}"
-
2
wrap_with :i, "", opts
-
end
-
-
1
def material_icon_tag icon, opts={}
-
26
add_class opts, "material-icons"
-
26
wrap_with :i, icon_class(:material, icon), opts
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/icon.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Navbar)
-
#
-
1
module Navbar;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/navbar.rb"; end
-
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# Options
-
# @param opts [Hash]
-
# @option opts [String, Hash<name, href>] brand
-
# @option opts [String] class
-
# @option opts [Boolean] no_collapse
-
# @option opts [:left, :right] toggle_align
-
1
def navbar id, opts={}
-
nav_opts = opts[:navbar_opts] || {}
-
nav_opts[:class] ||= opts[:class]
-
add_class nav_opts,
-
"navbar navbar-dark bg-#{opts.delete(:navbar_type) || 'primary'}"
-
content = yield
-
if opts[:no_collapse]
-
navbar_nocollapse content, nav_opts
-
else
-
navbar_responsive id, content, opts, nav_opts
-
end
-
end
-
-
1
def navbar_nocollapse content, nav_opts
-
# content = wrap_with(:div, content)
-
wrap_with :nav, content, nav_opts
-
end
-
-
1
def navbar_responsive id, content, opts, nav_opts
-
opts[:toggle_align] ||= :right
-
wrap_with :nav, nav_opts do
-
[
-
navbar_header(opts[:brand]),
-
navbar_toggle(id, opts[:toggle_align]),
-
wrap_with(:div, class: "collapse navbar-collapse",
-
id: "navbar-collapse-#{id}") { content }
-
]
-
end
-
end
-
-
1
def navbar_header brand
-
return "" unless brand
-
if brand.is_a? String
-
"<span class='navbar-brand'>#{brand}</span>"
-
else
-
link = brand[:href] || "#"
-
"<a class='navbar-brand' href='#{link}#'>#{brand[:name]}</a>"
-
end
-
end
-
-
1
def navbar_toggle id, align
-
content ||= %(<span class="navbar-toggler-icon"></span>)
-
<<-HTML
-
<button class="navbar-toggler navbar-toggler-#{align}" type="button" data-toggle="collapse" data-target="#navbar-collapse-#{id}" aria-controls="navbar-collapse-#{id}" aria-expanded="false" aria-label="Toggle navigation">
-
#{content}
-
</button>
-
HTML
-
end
-
-
1
def breadcrumb items
-
wrap_with :ol, class: "breadcrumb" do
-
items.map do |item|
-
wrap_with :li, item, class: "breadcrumb-item"
-
end.join
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/navbar.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Table)
-
#
-
1
module Table;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/table.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
class TableHelper
-
1
def initialize format, content, opts={}
-
@format = format
-
@div_table = opts.delete :div_table
-
@header = initialize_header opts[:header], content
-
@rows = content
-
@opts = opts
-
@format.add_class opts, :table
-
end
-
-
1
def render
-
tag :table, class: @opts[:class] do
-
[header, body]
-
end
-
end
-
-
1
def header
-
return unless @header
-
tag :thead do
-
tag :tr do
-
@header.map do |item|
-
tag(:th) { item }
-
end.join "\n"
-
end
-
end
-
end
-
-
1
def body
-
tag :tbody do
-
@rows.map do |row_content|
-
row row_content
-
end.join "\n"
-
end
-
end
-
-
1
def row row
-
row_data, row_class =
-
case row
-
when Hash then
-
[row.delete(:content), row]
-
else
-
[row, {}]
-
end
-
row_content =
-
if row_data.is_a?(Array)
-
row_data.map { |item| cell item }.join "\n"
-
else
-
row_data
-
end
-
tag :tr, row_content, row_class
-
end
-
-
1
def cell cell
-
if cell.is_a? Hash
-
content = cell.delete(:content).to_s
-
tag :td, cell do
-
content
-
end
-
else
-
tag :td do
-
String(cell)
-
end
-
end
-
end
-
-
1
def tag elem, content_or_opts={}, opts={}, &block
-
if @div_table
-
if content_or_opts.is_a? Hash
-
@format.add_class content_or_opts, elem
-
else
-
@format.add_class opts, elem
-
end
-
elem = :div
-
end
-
@format.wrap_with elem, content_or_opts, opts, &block
-
end
-
-
1
private
-
-
1
def initialize_header header, content
-
case header
-
when Array then header
-
when nil then nil
-
else content.shift
-
end
-
end
-
end
-
-
# @param [Array<Array,String>] content the content for the table. Accepts
-
# strings or arrays for each row.
-
# @param [Hash] opts
-
# @option opts [String, Array] :header use first row of content as header or
-
# value of this option if it is a string
-
# @return [HTML] bootstrap table
-
1
def table content, opts={}
-
TableHelper.new(self, content, opts).render
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/table.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Tabs)
-
#
-
1
module Tabs;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/tabs.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# @param tab_hash [Hash] keys are the tab names
-
# Each value can be either a String or a Hash.
-
# If a Hash can contain the following keys:
-
# :title - the label to appear in the clickable tab nav.
-
# if title is not specified, the key is used
-
# :content - body of tab pane
-
# :button_attr - attributes for button link in tab nav.
-
#
-
# If using lazy loading (see :load below), the following options also apply
-
# :path - explicit path to use for tab pane
-
# :view - card view from which to auto-construct path (if missing, uses key)
-
#
-
# If the value is a String, it is treated as the tab content for static tabs and
-
# the view for lazy tabs
-
#
-
# @param active_name [String] label of the tab that should be active at the
-
#
-
# @param [Hash] args options
-
# @option args [String] :tab_type ('tabs') use pills or tabs
-
# @option args [Hash] :panel_attr html args used for the panel div
-
# @option args [Hash] :pane_attr html args used for the pane div
-
# @option args [Hash] :load. `:lazy` for lazy-loading tabs
-
#
-
# @param [Block] block content of the active tab (for lazy-loading)
-
# beginning (default is the first)
-
#
-
# @return [HTML] bootstrap tabs element with all content preloaded
-
1
def tabs tab_hash, active_name=nil, args={}, &block
-
1
klass = args[:load] == :lazy ? Card::LazyTab : Card::Tab
-
1
args.reverse_merge!(
-
panel_attr: {},
-
pane_attr: {},
-
tab_type: "tabs",
-
block: block,
-
tab_objects: Card::Tab.tab_objects(self, tab_hash, active_name, klass)
-
)
-
1
haml :tab_panel, args
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/tabs.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Bootstrap;
-
# Set: All cards (Bootstrap, Wrapper)
-
#
-
1
module Wrapper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/wrapper.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def frame
-
20
class_up "d0-card-header" , "card-header"
-
20
class_up "d0-card-body", "card-body card-text"
-
20
super
-
end
-
-
1
def standard_frame slot=true
-
20
if panel_state
-
class_up "d0-card-frame", "card bg-#{panel_state} text-white"
-
else
-
20
class_up "d0-card-frame", "card"
-
end
-
20
super
-
end
-
-
1
def panel_state
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/bootstrap/wrapper.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (RichBootstrap)
-
#
-
1
module RichBootstrap;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/rich_bootstrap.rb"; end
-
1
def read_bootstrap_variables
-
path = ::File.expand_path(
-
"#{mod_root :bootstrap}/vendor/bootstrap/scss/_variables.scss", __FILE__
-
)
-
::File.exist?(path) ? ::File.read(path) : ""
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :closed do
-
1
class_up "d0-card-body", "closed-content"
-
1
super()
-
end
-
-
1
include Bootstrapper
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/all/rich_bootstrap.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "BootstrapCore"
-
#
-
1
module BootstrapCore;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/bootstrap_core.rb"; end
-
1
include_set Abstract::BootstrapCodeFile
-
-
1
def load_stylesheets
-
1
add_bs_stylesheet "variables"
-
1
add_bs_subdir "mixins"
-
1
%w[ print reboot type images code grid tables forms buttons transitions dropdown
-
button-group input-group custom-forms nav navbar card breadcrumb pagination badge
-
jumbotron alert progress media list-group close modal tooltip popover carousel
-
].each do |name|
-
30
add_bs_stylesheet name
-
end
-
1
add_bs_subdir "utilities"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/bootstrap_core.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "BootstrapFunctions"
-
#
-
1
module BootstrapFunctions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/bootstrap_functions.rb"; end
-
1
include_set Abstract::BootstrapCodeFile
-
-
1
def load_stylesheets
-
1
add_bs_stylesheet "functions"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/bootstrap_functions.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "FontAwesome"
-
#
-
1
module FontAwesome;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/font_awesome.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::StyleLibraries.add_item :font_awesome
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/font_awesome.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "MaterialIcons"
-
#
-
1
module MaterialIcons;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/material_icons.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::StyleLibraries.add_item :material_icons
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/material_icons.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptBootstrap"
-
#
-
1
module ScriptBootstrap;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/script_bootstrap.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::ScriptLibraries.add_item :script_bootstrap
-
-
1
def source_dir
-
""
-
end
-
-
1
def source_files
-
%w[vendor/bootstrap/dist/js/bootstrap.bundle.js
-
lib/javascript/bootstrap_modal_decko.js
-
vendor/bootstrap-colorpicker/dist/js/bootstrap-colorpicker.min.js]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/script_bootstrap.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptLoadSelect2"
-
#
-
1
module ScriptLoadSelect2;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/script_load_select2.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::ScriptMods.add_item :script_load_select2
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/script_load_select2.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptSelect2"
-
#
-
1
module ScriptSelect2;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/script_select2.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::ScriptLibraries.add_item :script_select2
-
-
1
def source_files
-
# full version of select2 is needed to support containerCssClass config option
-
# which we need for select2_bootstrap to work properly
-
"vendor/select2/dist/js/select2.full.min.js"
-
end
-
-
1
def source_dir
-
""
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/script_select2.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "SmartmenuCss"
-
#
-
1
module SmartmenuCss;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/smartmenu_css.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
def source_files
-
"startmenu.css"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/smartmenu_css.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "SmartmenuJs"
-
#
-
1
module SmartmenuJs;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/smartmenu_js.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
def source_files
-
"startmenu.js"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/smartmenu_js.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleBootstrapCards"
-
#
-
1
module StyleBootstrapCards;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_bootstrap_cards.rb"; end
-
1
include_set Abstract::CodeFile
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_bootstrap_cards.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleBootstrapColorpicker"
-
#
-
1
module StyleBootstrapColorpicker;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_bootstrap_colorpicker.rb"; end
-
1
include_set Abstract::BootstrapCodeFile
-
1
Self::StyleLibraries.add_item :style_bootstrap_colorpicker
-
-
1
def load_stylesheets
-
1
add_stylesheet_file "vendor/bootstrap-colorpicker/src/sass/_colorpicker.scss"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_bootstrap_colorpicker.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleSelect2"
-
#
-
1
module StyleSelect2;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_select2.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::StyleLibraries.add_item :style_select2
-
-
1
def source_files
-
2
["vendor/select2/dist/css/select2.css", "lib/stylesheets/style_select2_bootstrap.scss"]
-
end
-
-
1
def source_dir
-
4
""
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_select2.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleSelect2Bootstrap"
-
#
-
1
module StyleSelect2Bootstrap;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_select2_bootstrap.rb"; end
-
1
include_set Abstract::CodeFile
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/self/style_select2_bootstrap.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "BootswatchSkin" cards
-
#
-
1
module BootswatchSkin;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type/bootswatch_skin.rb"; end
-
1
include_set Abstract::BootswatchTheme
-
-
# override to customize the theme or to make it customizable
-
# @return [Card, String, Array<Card, String>] strings must be valid (s)css; cards
-
# must be of type (S)CSS
-
1
def variables_content
-
1
scss_from_theme_file :variables
-
end
-
-
# override to customize the theme or to make it customizable
-
# @return [Card, String, Array<Card,String>] strings must be valid (s)css; cards
-
# must be of type (S)CSS
-
1
def stylesheets_content
-
1
scss_from_theme_file :bootswatch
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type/bootswatch_skin.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "CustomizedBootswatchSkin" cards
-
#
-
1
module CustomizedBootswatchSkin;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type/customized_bootswatch_skin.rb"; end
-
1
include_set Abstract::BootswatchTheme
-
-
1
card_accessor :colors
-
1
card_accessor :variables
-
1
card_accessor :stylesheets
-
-
1
def top_level_item_cards
-
cards = PRE_VARIABLES_CARD_NAMES.map { |n| Card[n] }
-
cards += [colors_card, variables_card]
-
cards += POST_VARIABLES_CARD_NAMES.map { |n| Card[n] }
-
cards << stylesheets_card
-
cards
-
end
-
-
1
def editable_item_cards
-
[colors_card, variables_card, stylesheets_card]
-
end
-
-
1
def variables_card_names
-
%i[colors variables].map { |s| Card.fetch_name name, s }
-
end
-
-
1
def stylesheets_card_names
-
[Card.fetch_name(name, :stylesheets)]
-
end
-
-
1
def theme_card_name
-
"#{theme_name} skin"
-
end
-
-
1
def theme_name
-
Env.params[:theme].present? && Env.params[:theme]
-
end
-
-
1
def theme_codename
-
theme_name && "#{theme_name}_skin".to_sym
-
end
-
-
1
event :validate_theme_template, :validate, on: :create do
-
if theme_name
-
if Card.fetch_type_id(theme_card_name) != Card::BootswatchSkinID
-
errors.add :abort, tr(:not_valid_theme, theme_name: theme_name)
-
elsif !Dir.exist? source_dir
-
puts method(:source_dir).source_location
-
errors.add :abort, tr(:cannot_source_theme, theme_name: theme_name)
-
end
-
end
-
end
-
-
1
event :initialize_because_of_type_change, :prepare_to_store,
-
on: :update, changed: :type do
-
initialize_theme old_skin_items
-
end
-
-
1
def old_skin_items
-
skin = Card.new(type: :pointer, content: db_content_before_act)
-
skin.drop_item "bootstrap default skin"
-
skin.item_names
-
end
-
-
1
event :copy_theme, :prepare_to_store, on: :create do
-
initialize_theme
-
end
-
-
1
def initialize_theme style_item_names=nil
-
add_subfield :colors, type_id: Card::ScssID
-
add_variables_subfield
-
add_stylesheets_subfield style_item_names
-
end
-
-
1
def add_stylesheets_subfield style_items=nil
-
opts = { type_id: Card::SkinID }
-
if theme_name
-
theme_style = add_bootswatch_subfield
-
opts[:content] = "[[#{theme_style.name}]]"
-
end
-
if style_items
-
opts[:content] = [opts[:content], style_items].flatten.compact.to_pointer_content
-
end
-
-
add_subfield :stylesheets, opts
-
end
-
-
1
def add_variables_subfield
-
theme_content = content_from_theme(:variables)
-
default_content = read_bootstrap_variables
-
add_subfield :variables,
-
type_id: Card::ScssID,
-
content: "#{theme_content}\n\n\n#{default_content}"
-
end
-
-
1
def add_bootswatch_subfield
-
add_subfield :bootswatch, type_id: Card::ScssID,
-
content: content_from_theme(:bootswatch)
-
end
-
-
1
def theme_card
-
@theme_card ||= theme_codename ? Card[theme_codename] : nil
-
end
-
-
1
def content_from_theme subfield
-
theme_card&.scss_from_theme_file subfield
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def edit_fields
-
[[:colors, { title: "" }],
-
[:variables, { title: "Variables" }],
-
[:stylesheets, { title: "Styles" }]]
-
end
-
-
1
view :one_line_content do
-
""
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type/customized_bootswatch_skin.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Type; module CustomizedBootswatchSkin;
-
# Set: All "CustomizedBootswatchSkin+HtmlViews" cards (HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
2
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type/customized_bootswatch_skin/html_views.rb"; end
-
1
include_set Abstract::Media
-
1
include_set Abstract::BsBadge
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :menu do
-
""
-
end
-
-
1
def short_content
-
""
-
# labeled_badge card.item_count, "items"
-
# "#{card.item_count} items"
-
end
-
-
1
view :core, template: :haml
-
-
1
info_bar_cols 6, 3, 3
-
-
1
before :bar do
-
super()
-
voo.show :edit_button, :bar_middle
-
class_up "bar-middle", "p-3 align-items-center p-0"
-
end
-
-
1
view :bar_right do
-
render(:short_content)
-
end
-
-
1
before :bar_nav do
-
voo.hide :edit_link
-
end
-
-
1
view :bar_bottom do
-
render_core
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type/customized_bootswatch_skin/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class TypePlusRight; module CustomizedBootswatchSkin;
-
# Set: All "+Colors" cards on "CustomizedBootswatchSkin" cards
-
#
-
1
module Colors;
-
1
extend Card::Set
-
3
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type_plus_right/customized_bootswatch_skin/colors.rb"; end
-
VARIABLE_NAMES = {
-
1
colors: %i[blue indigo purple pink red orange yellow green teal cyan
-
white gray-100 gray-200 gray-300 gray-400 gray-500 gray-600 gray-700 gray-800
-
gray-900 black],
-
theme_colors: %i[primary secondary success info warning danger light dark
-
body-bg body-color]
-
}.freeze
-
-
# temporarily removed: link-color card-bg card-cap-bg
-
# bootstrap default for link-color uses the theme-color function which
-
# has to be defined between the theme-colors and that variable
-
# (see bootstrap's _variables.scss)
-
# TODO: deal with that
-
-
# @param name [String] a scss variable name (it can start with a $)
-
1
def variable_value name
-
value_from_scss(name, content) ||
-
value_from_variables_card(name) ||
-
default_value_from_bootstrap(name)
-
end
-
-
1
def value_from_scss name, source
-
name = name.to_s
-
name = name[1..-1] if name.start_with?("$")
-
source.match(definition_regex(name))&.capture(:value)
-
end
-
-
1
def value_from_variables_card name
-
return unless (var_card = left.variables_card) && var_card.content.present?
-
value_from_scss name, var_card.content
-
end
-
-
1
def definition_regex name
-
/^(?<before>\s*\$#{name}\:\s*)(?<value>.+?)(?<after> !default;)$/
-
end
-
-
1
def default_value_from_bootstrap name
-
value_from_scss name, bootstrap_variables_scss
-
end
-
-
1
def bootstrap_variables_scss
-
@bootstrap_variables_scss ||= read_bootstrap_variables
-
end
-
-
1
def colors
-
@colors ||= variable_group_with_values :colors
-
end
-
-
1
def theme_colors
-
@theme_colors ||= variable_group_with_values :theme_colors
-
end
-
-
1
def variable_group_with_values group
-
VARIABLE_NAMES[group].each_with_object({}) do |name, h|
-
h[name] = variable_value name
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :input, template: :haml do
-
@colors = card.colors
-
@theme_colors = card.theme_colors
-
end
-
-
1
def theme_color_picker name, value
-
# value = value[1..-1] if value.start_with? "$"
-
options = VARIABLE_NAMES[:colors].map { |var| "$#{var}" }
-
options << value unless options.include? value
-
select_tag "theme_colors[#{name}]", options_for_select(options, value),
-
class: "tags form-control"
-
end
-
-
1
before :bar_right do
-
voo.show :edit_button
-
end
-
-
1
view :core, template: :haml do
-
@colors = card.theme_colors.reject { |k, _v| k.in? %i[body-bg body-color] }
-
end
-
-
1
view :bar_middle do
-
<<-HTML
-
<div class="colorpicker-element">
-
<div class="input-group-addon">
-
<span class="bg-body border p-1">Text</span>
-
<span class="bg-dark text-light border p-1">Nav</span>
-
<i class="bg-primary"></i>
-
<i class="bg-secondary"></i>
-
</div>
-
</div>
-
HTML
-
end
-
end
-
-
1
event :translate_variables_to_scss, :prepare_to_validate, on: :update do
-
replace_values :colors
-
replace_values :theme_colors
-
end
-
-
1
def replace_values group, prefix=""
-
values = variable_values_from_params group
-
values.each_pair do |name, val|
-
if content.match definition_regex(name)
-
content.gsub! definition_regex(name), "\\k<before>#{prefix}#{val}\\k<after>"
-
else
-
self.content += "$#{name}: #{prefix}#{val} !default;\n"
-
end
-
end
-
end
-
-
1
def variable_values_from_params group
-
Env.params.dig(group)&.slice(*VARIABLE_NAMES[group]) || {}
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-bootstrap/set/type_plus_right/customized_bootswatch_skin/colors.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (History)
-
#
-
1
module History;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history.rb"; end
-
1
event :update_ancestor_timestamps, :integrate do
-
314
ids = history_ancestor_ids
-
314
return unless ids.present?
-
6
Card.where(id: ids).update_all(updater_id: Auth.current_id, updated_at: Time.now)
-
12
ids.map { |anc_id| Card.expire anc_id.cardname }
-
end
-
-
# track history (acts, actions, changes) on this card
-
1
def history?
-
666
true
-
end
-
-
# all cards whose acts are considered part of this card's history
-
1
def history_card_ids
-
nestee_ids << id
-
end
-
-
# all cards who are considered updated if this card's was updated
-
1
def history_parent_ids
-
640
nester_ids
-
end
-
-
1
def history_ancestor_ids recursion_level=0
-
320
return [] if recursion_level > 5
-
-
320
ids = history_parent_ids +
-
6
history_parent_ids.map { |id| Card[id].history_ancestor_ids(recursion_level + 1) }
-
320
ids.flatten
-
end
-
-
# ~~FIXME~~: optimize (no need to instantiate all actions and changes!)
-
# Nothing is instantiated here. ActiveRecord is much smarter than you think.
-
# Methods like #empty? and #size make sql queries if their receivers are not already
-
# loaded -pk
-
1
def first_change?
-
# = update or delete
-
294
@current_action.action_type != :create && action_count == 2 &&
-
create_action.card_changes.empty?
-
end
-
-
1
def first_create?
-
294
@current_action.action_type == :create && action_count == 1
-
end
-
-
1
def action_count
-
294
Card::Action.where(card_id: @current_action.card_id).count
-
end
-
-
# card has account that is responsible for prior acts
-
1
def has_edits?
-
Card::Act.where(actor_id: id).where("card_id IS NOT NULL").present?
-
end
-
-
1
def changed_fields
-
421
Card::Change::TRACKED_FIELDS & (changed_attribute_names_to_save | saved_changes.keys)
-
end
-
-
1
def nestee_ids
-
requiring_id { @nestee_ids ||= nesting_ids(:referee_id, :referer_id) }
-
end
-
-
1
def nester_ids
-
1280
requiring_id { @nester_ids ||= nesting_ids(:referer_id, :referee_id) }
-
end
-
-
1
def diff_args
-
{ diff_format: :text }
-
end
-
-
# Delete all changes and old actions and make the last action the create action
-
# (that way the changes for that action will be created with the first update)
-
1
def make_last_action_the_initial_action
-
delete_all_changes
-
old_actions.delete_all
-
last_action.update! action_type: :create
-
end
-
-
1
def clear_history
-
delete_all_changes
-
delete_old_actions
-
end
-
-
1
def delete_old_actions
-
old_actions.delete_all
-
end
-
-
1
def delete_all_changes
-
Card::Change.where(card_action_id: all_action_ids).delete_all
-
end
-
-
1
def save_content_draft content
-
super
-
acts.create do |act|
-
act.ar_actions.build(draft: true, card_id: id, action_type: :update)
-
.card_changes.build(field: :db_content, value: content)
-
end
-
end
-
-
1
private
-
-
1
def nesting_ids return_field, where_field
-
302
Card::Reference.select(return_field).distinct.where(
-
ref_type: "I", where_field => id
-
).pluck(return_field).compact
-
end
-
-
1
def requiring_id
-
640
id ? yield : (return [])
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, ActListing)
-
#
-
1
module ActListing;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/act_listing.rb"; end
-
1
ACTS_PER_PAGE = Card.config.acts_per_page
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def act_from_context
-
if (act_id = params["act_id"])
-
Act.find(act_id) || raise(Card::NotFound, "act not found")
-
else
-
card.last_action.act
-
end
-
end
-
-
# used (by history and recent)for rendering act lists with legend and paging
-
#
-
# @param acts [ActiveRecord::Relation] relation that will return acts objects
-
# @param context [Symbol] :relative or :absolute
-
# @param draft_legend [Symbol] :show or :hide
-
1
def acts_layout acts, context, draft_legend=:hide
-
bs_layout container: false, fluid: false do
-
html _render_act_legend(draft_legend => :draft_legend)
-
row(12) { act_list acts, context }
-
row(12) { act_paging acts, context }
-
end
-
end
-
-
1
def act_list acts, context
-
act_accordion acts, context do |act, seq|
-
fmt = context == :relative ? self : act.card.format(:html)
-
fmt.act_listing act, seq, context
-
end
-
end
-
-
1
def act_listing act, seq=nil, context=nil
-
opts = act_listing_opts_from_params(seq)
-
opts[:slot_class] = "revision-#{act.id} history-slot list-group-item"
-
context ||= (params[:act_context] || :absolute).to_sym
-
act_renderer(context).new(self, act, opts).render
-
end
-
-
# TODO: consider putting all these under one top-level param, eg:
-
# act: { seq: X, diff: [show/hide], action_view: Y }
-
1
def act_listing_opts_from_params seq
-
{ act_seq: (seq || params["act_seq"]),
-
action_view: (params["action_view"] || "summary").to_sym,
-
hide_diff: params["hide_diff"].to_s.strip == "true" }
-
end
-
-
1
def act_accordion acts, context, &block
-
accordion_group acts_for_accordion(acts, context, &block), nil, class: "clear-both"
-
end
-
-
1
def acts_for_accordion acts, context
-
clean_acts(current_page_acts(acts)).map do |act|
-
with_act_seq(context, acts) do |seq|
-
yield act, seq
-
end
-
end
-
end
-
-
1
def with_act_seq context, acts
-
yield(context == :absolute ? nil : current_act_seq(acts))
-
end
-
-
1
def current_act_seq acts
-
@act_seq = @act_seq ? (@act_seq -= 1) : act_list_starting_seq(acts)
-
end
-
-
1
def clean_acts acts
-
# FIXME: if we get rid of bad act data, this will not be necessary
-
# The current
-
acts.select(&:card)
-
end
-
-
1
def current_page_acts acts
-
acts.page(acts_page_from_params).per acts_per_page
-
end
-
-
1
def act_list_starting_seq acts
-
acts.size - (acts_page_from_params - 1) * acts_per_page
-
end
-
-
1
def acts_per_page
-
@acts_per_page || ACTS_PER_PAGE
-
end
-
-
1
def acts_page_from_params
-
@acts_page_from_params ||= params["page"].present? ? params["page"].to_i : 1
-
end
-
-
1
def act_paging acts, context
-
wrap_with :div, class: "slotter btn-sm" do
-
acts = current_page_acts acts
-
opts = { remote: true, theme: "twitter-bootstrap-4" }
-
opts[:total_pages] = 10 if limited_paging? context
-
paginate acts, opts
-
end
-
end
-
-
1
def limited_paging? context
-
context == :absolute && Act.count > 1000
-
end
-
-
1
def action_icon action_type, extra_class=nil
-
icon = case action_type
-
when :create then :add_circle
-
when :update then :pencil
-
when :delete then :remove_circle
-
when :draft then :wrench
-
end
-
icon_tag icon, extra_class
-
end
-
-
1
private
-
-
1
def act_renderer context
-
case context
-
when :absolute
-
Act::ActRenderer::AbsoluteActRenderer
-
when :bridge
-
Act::ActRenderer::BridgeActRenderer
-
else # relative
-
Act::ActRenderer::RelativeActRenderer
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/act_listing.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, Actions)
-
#
-
# -*- encoding : utf-8 -*-
-
1
module Actions;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/actions.rb"; end
-
-
1
def all_action_ids
-
Card::Action.where(card_id: id).pluck :id
-
end
-
-
1
def action_from_id action_id
-
26
return unless action_id.is_a?(Integer) || action_id =~ /^\d+$/
-
-
# if not an integer revision id is probably a mod (e.g. if you request
-
# files/:logo/standard.png)
-
action = Action.fetch action_id
-
return unless action.card_id == id
-
-
action
-
end
-
-
1
def old_actions
-
actions.where("id != ?", last_action_id)
-
end
-
-
1
def create_action
-
293
@create_action ||= actions.first
-
end
-
-
1
def nth_action index
-
29
index = index.to_i
-
29
return unless id && index.positive?
-
-
3
Action.where("draft is not true AND card_id = #{id}")
-
.order(:id).limit(1).offset(index - 1).first
-
end
-
-
1
def new_content_action_id
-
159
return unless @current_action && current_action_changes_content?
-
-
32
@current_action.id
-
end
-
-
1
def current_action_changes_content?
-
32
new_card? || @current_action.new_content? || db_content_is_changing?
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def action_from_context
-
if (action_id = voo.action_id || params[:action_id])
-
Action.fetch action_id
-
else
-
card.last_action
-
end
-
end
-
-
1
def action_content action, view_type
-
return "" unless action.present?
-
-
wrap do
-
[action_content_toggle(action, view_type),
-
content_diff(action, view_type)]
-
end
-
end
-
-
1
def content_diff action, view_type
-
diff = action.new_content? && content_changes(action, view_type)
-
return "<i>empty</i>" unless diff.present?
-
-
diff
-
end
-
-
1
def action_content_toggle action, view_type
-
return unless show_action_content_toggle?(action, view_type)
-
-
toggle_action_content_link action, view_type
-
end
-
-
1
def show_action_content_toggle? action, view_type
-
view_type == :expanded || action.summary_diff_omits_content?
-
end
-
-
1
def toggle_action_content_link action, view_type
-
other_view_type = view_type == :expanded ? :summary : :expanded
-
css_class = "revision-#{action.card_act_id} float-right"
-
link_to_view "action_#{other_view_type}",
-
icon_tag(action_arrow_dir(view_type), class: "md-24"),
-
class: css_class,
-
path: { action_id: action.id, look_in_trash: true }
-
end
-
-
1
def action_arrow_dir view_type
-
view_type == :expanded ? :triangle_left : :triangle_right
-
end
-
-
1
def revert_actions_link link_text, path_args, html_args={}
-
return unless card.ok? :update
-
-
path_args.reverse_merge! action: :update, look_in_trash: true, assign: true,
-
card: { skip: :validate_renaming }
-
html_args.reverse_merge! remote: true, method: :post, rel: "nofollow", path: path_args
-
add_class html_args, "slotter"
-
link_to link_text, html_args
-
end
-
-
1
def action_legend
-
types = %i[create update delete]
-
legend = types.map do |action_type|
-
"#{action_icon(action_type)} #{action_type}d"
-
end
-
legend << _render_draft_legend if voo.show?(:draft_legend)
-
"<small>Actions: #{legend.join ' | '}</small>"
-
end
-
-
1
def content_legend
-
legend = [Card::Content::Diff.render_added_chunk("Additions"),
-
Card::Content::Diff.render_deleted_chunk("Subtractions")]
-
"<small>Content changes: #{legend.join ' | '}</small>"
-
end
-
-
1
def content_changes action, diff_type, hide_diff=false
-
if hide_diff
-
action.raw_view
-
else
-
action.content_diff diff_type
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/actions.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, Acts)
-
#
-
# all acts with actions on self and on cards included in self (ie, acts shown in history)
-
1
module Acts;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/acts.rb"; end
-
1
def history_acts
-
@history_acts ||= Act.all_with_actions_on(history_card_ids, true).order id: :desc
-
end
-
-
1
def draft_acts
-
drafts.created_by(Card::Auth.current_id).map(&:act)
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/acts.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, Events)
-
#
-
# must be called on all actions and before :set_name, :process_subcards and
-
1
module Events;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/events.rb"; end
-
# :validate_delete_children
-
1
event :assign_action, :initialize, when: :actionable? do
-
316
act = director.need_act
-
316
@current_action = Card::Action.create(
-
card_act_id: act.id,
-
action_type: action,
-
316
draft: (Env.params["draft"] == "true")
-
)
-
316
if @supercard && @supercard != self
-
150
@current_action.super_action = @supercard.current_action
-
end
-
end
-
-
# can we store an action? (can be overridden, eg in files)
-
1
def actionable?
-
650
history?
-
end
-
-
1
event :detect_conflict, :validate, on: :update, when: :edit_conflict? do
-
errors.add :conflict, tr(:error_not_latest_revision)
-
end
-
-
1
def edit_conflict?
-
58
last_action_id_before_edit &&
-
last_action_id_before_edit.to_i != last_action_id &&
-
(la = last_action) &&
-
la.act.actor_id != Auth.current_id
-
end
-
-
# stores changes in the changes table and assigns them to the current action
-
# removes the action if there are no changes
-
1
event :finalize_action, :finalize, when: :finalize_action? do
-
303
if changed_fields.present?
-
294
@current_action.update! card_id: id
-
-
# Note: #last_change_on uses the id to sort by date
-
# so the changes for the create changes have to be created before the first change
-
294
store_card_changes_for_create_action if first_change?
-
294
store_card_changes unless first_create?
-
# FIXME: a `@current_action.card` call here breaks specs in solid_cache_spec.rb
-
9
elsif @current_action.card_changes.reload.empty?
-
9
@current_action.delete
-
9
@current_action = nil
-
end
-
end
-
-
# changes for the create action are stored after the first update
-
1
def store_card_changes_for_create_action
-
97
Card::Action.cache.delete "#{create_action.id}-changes"
-
97
store_each_history_field create_action.id do |field|
-
582
attribute_before_act field
-
end
-
end
-
-
1
def store_card_changes
-
118
store_each_history_field @current_action.id, changed_fields do |field|
-
153
self[field]
-
end
-
end
-
-
1
def store_each_history_field action_id, fields=nil
-
215
fields ||= Card::Change::TRACKED_FIELDS
-
if false # Card::Change.supports_import?
-
# attach.feature fails with this
-
values = fields.map.with_index { |field, index| [index, yield(field), action_id] }
-
Card::Change.import [:field, :value, :card_action_id], values #, validate: false
-
else
-
215
fields.each do |field|
-
735
Card::Change.create field: field,
-
value: yield(field),
-
card_action_id: action_id
-
end
-
end
-
end
-
-
1
def finalize_action?
-
318
actionable? && current_action
-
end
-
-
1
event :rollback_actions, :prepare_to_validate, on: :update, when: :rollback_request? do
-
update_args = process_revert_actions
-
Env.params["revert_actions"] = nil
-
update! update_args
-
clear_drafts
-
abort :success
-
end
-
-
1
event :finalize_act, after: :finalize_action, when: :act_card? do
-
140
Card::Director.act.update! card_id: id
-
end
-
-
1
event :remove_empty_act, :integrate_with_delay_final, when: :remove_empty_act? do
-
# Card::Director.act.delete
-
# Card::Director.act = nil
-
end
-
-
1
def remove_empty_act?
-
314
act_card? && Director.act&.ar_actions&.reload&.empty?
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/events.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, Last)
-
#
-
1
module Last;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/last.rb"; end
-
1
def acted_at
-
last_act.acted_at
-
end
-
-
1
def revised_at
-
(last_action && (act = last_action.act) && act.acted_at) || Time.zone.now
-
end
-
-
1
def last_change_on field, opts={}
-
1
action_id = extract_action_id(opts[:before] || opts[:not_after])
-
-
# If there is only one action then there are no entries in the changes table,
-
# so we can't do a sql search but the changes are accessible via the action.
-
1
if no_last_change? action_id, opts[:before]
-
nil
-
1
elsif create_action_last_change? action_id
-
create_action&.change field
-
else
-
1
last_change_from_action_id action_id, field, opts
-
end
-
end
-
-
1
def no_last_change? action_id, before
-
1
before && action_id == create_action.id
-
end
-
-
1
def create_action_last_change? action_id
-
1
action_id == create_action&.id || (!action_id && create_action&.sole?)
-
end
-
-
1
def last_change_from_action_id action_id, field, opts
-
1
Change.joins(:action).where(
-
last_change_sql_conditions(opts),
-
card_id: id,
-
action_id: action_id,
-
field: Card::Change.field_index(field)
-
).order(:id).last
-
end
-
-
1
def last_change_sql_conditions opts
-
1
cond = "card_actions.card_id = :card_id AND field = :field"
-
1
cond += " AND (draft is not true)" unless opts[:including_drafts]
-
1
operator = "<" if opts[:before]
-
1
operator = "<=" if opts[:not_after]
-
1
cond += " AND card_action_id #{operator} :action_id" if operator
-
1
cond
-
end
-
-
1
def last_action_id
-
1
last_action&.id
-
end
-
-
1
def last_action
-
7
actions.where("id IS NOT NULL").last
-
end
-
-
1
def last_content_action
-
last_change_on(:db_content)&.action
-
end
-
-
1
def last_content_action_id
-
last_change_on(:db_content)&.card_action_id
-
end
-
-
1
def last_actor
-
last_act.actor
-
end
-
-
1
def last_act
-
@last_act ||=
-
if (action = last_action)
-
last_act_on_self = acts.last
-
act_of_last_action = action.act
-
return act_of_last_action unless last_act_on_self
-
return last_act_on_self unless act_of_last_action
-
-
return last_act_on_self if act_of_last_action == last_act_on_self
-
-
if last_act_on_self.acted_at > act_of_last_action.acted_at
-
last_act_on_self
-
else
-
act_of_last_action
-
end
-
end
-
end
-
-
1
def previous_action action_id
-
return unless action_id
-
-
action_index = actions.find_index { |a| a.id == action_id }
-
all_actions[action_index - 1] if action_index.to_i.nonzero?
-
end
-
-
1
private
-
-
1
def extract_action_id action_arg
-
1
action_arg.is_a?(Card::Action) ? action_arg.id : action_arg
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/last.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, Revision)
-
#
-
1
module Revision;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/revision.rb"; end
-
1
def revision action, before_action=false
-
# a "revision" refers to the state of all tracked fields
-
# at the time of a given action
-
action = Card::Action.fetch(action) if action.is_a? Integer
-
return unless action
-
-
if before_action
-
revision_before_action action
-
else
-
revision_attributes action
-
end
-
end
-
-
1
def revision_attributes action
-
Card::Change::TRACKED_FIELDS.each_with_object({}) do |field, attr_changes|
-
last_change = action.change(field) || last_change_on(field, not_after: action)
-
attr_changes[field.to_sym] = (last_change ? last_change.value : self[field])
-
end
-
end
-
-
1
def revision_before_action action
-
if (prev_action = action.previous_action)
-
revision prev_action
-
else
-
{ trash: true }
-
end
-
end
-
-
1
def rollback_request?
-
58
history? && actions_to_revert.any?
-
end
-
-
1
def process_revert_actions revert_actions=nil
-
revert_actions ||= actions_to_revert
-
update_args = { subcards: {} }
-
reverting_to_previous = Env.params["revert_to"] == "previous"
-
revert_actions.each do |action|
-
merge_revert_action! action, update_args, reverting_to_previous
-
end
-
update_args
-
end
-
-
1
def actions_to_revert
-
47
if (act_id = Env.params["revert_act"])
-
Act.find(act_id).actions
-
else
-
47
explicit_actions_to_revert
-
end
-
end
-
-
1
def explicit_actions_to_revert
-
47
Array.wrap(Env.params["revert_actions"]).map do |a_id|
-
Action.fetch(a_id) || nil
-
end.compact
-
end
-
-
1
def merge_revert_action! action, update_args, reverting_to_previous
-
rev = action.card.revision(action, reverting_to_previous)
-
rev.delete :name unless rev[:name] # handles null name field in compound cards
-
if action.card_id == id
-
update_args.merge! rev
-
else
-
update_args[:subcards][action.card.name] = rev
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/revision.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, Selected)
-
#
-
# if these aren't in a nested module, the methods just overwrite the base
-
# methods, but we need a distinct module so that super will be able to refer to
-
1
module Selected;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/selected.rb"; end
-
# the base methods.
-
1
def content
-
2609
@selected_action_id ? selected_content : super
-
end
-
-
1
def content= value
-
57
@selected_content = nil
-
57
super
-
end
-
-
1
def select_action_by_params params
-
26
action = nth_action(params[:rev]) || action_from_id(params[:rev_id])
-
26
return unless action
-
-
select_action action.id
-
end
-
-
1
def select_action action_id
-
run_callbacks :select_action do
-
self.selected_action_id = action_id
-
end
-
end
-
-
1
def selected_action_id
-
@selected_action_id || (@current_action&.id) || last_action_id
-
end
-
-
1
def selected_action_id= action_id
-
@selected_content = nil
-
@selected_action_id = action_id
-
end
-
-
1
def selected_action
-
selected_action_id && Action.fetch(selected_action_id)
-
end
-
-
1
def selected_content
-
@selected_content ||= content_at_time_of_selected_action || db_content
-
end
-
-
1
def content_at_time_of_selected_action
-
lc = last_change_on(:db_content, not_after: @selected_action_id, including_drafts: true)
-
lc&.value
-
end
-
-
1
def with_selected_action_id action_id
-
current_action_id = @selected_action_id
-
select_action_id action_id
-
result = yield
-
select_action_id current_action_id
-
result
-
end
-
-
1
def select_action_id action_id
-
run_callbacks :select_action do
-
self.selected_action_id = action_id
-
end
-
end
-
-
1
def selected_content_action_id
-
159
@selected_action_id || new_content_action_id || last_content_action_id
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/selected.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module History;
-
# Set: All cards (History, Views)
-
#
-
# History views
-
1
module Views;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/views.rb"; end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :history, cache: :never do
-
frame do
-
class_up "d0-card-body", "history-slot"
-
acts_layout card.history_acts, :relative, :show
-
end
-
end
-
-
1
view :act, cache: :never do
-
act_listing act_from_context
-
end
-
-
1
view :act_legend do
-
bs_layout do
-
row md: [12, 12], lg: [7, 5] do
-
col action_legend
-
col content_legend, class: "text-right"
-
end
-
end
-
end
-
-
1
view :draft_legend do
-
"#{action_icon(:draft)} unsaved draft"
-
end
-
-
1
view :action_summary do
-
action_content action_from_context, :summary
-
end
-
-
1
view :action_expanded do
-
action_content action_from_context, :expanded
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history/views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (HistoryBridge)
-
#
-
1
module HistoryBridge;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history_bridge.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :creator_credit,
-
wrap: { div: { class: "text-muted creator-credit" } }, cache: :never do
-
return "" unless card.real?
-
"Created by #{nest card.creator, view: :link} "\
-
"#{time_ago_in_words(card.created_at)} ago"
-
end
-
-
1
view :updated_by, wrap: { div: { class: "text-muted" } } do
-
return "" unless card.id
-
updaters = Card.search(updater_of: { id: card.id })
-
return "" unless updaters.present?
-
-
updaters = updater_links updaters, others_target: Card.fetch(card, :editors)
-
"Updated by #{updaters}"
-
end
-
-
1
def updater_links updaters, item_view: :link, max_count: 3, others_target: card
-
return "" unless updaters.present?
-
-
total = updaters.size
-
fetch_count = total > max_count ? max_count - 1 : max_count
-
-
reduced = first_card(fetch_count).map { |c| nest c, view: item_view }
-
if total > max_count
-
reduced << link_to_card(others_target, "#{total - fetch_count} others")
-
end
-
reduced.to_sentence
-
end
-
-
1
def acts_bridge_layout acts, context=:bridge
-
output [
-
_render_creator_credit,
-
act_link_list(acts, context),
-
act_paging(acts, context)
-
]
-
end
-
-
1
def act_link_list acts, context
-
items = acts_for_accordion(acts, context) do |act, seq|
-
act_link_list_item act, seq, context
-
end
-
bridge_pills items
-
end
-
-
1
def act_link_list_item act, seq=nil, _context=nil
-
opts = act_listing_opts_from_params(seq)
-
opts[:slot_class] = "revision-#{act.id} history-slot nav-item"
-
act_renderer(:bridge).new(self, act, opts).bridge_link
-
end
-
-
1
def act_list_group acts, context, &block
-
list_group acts_for_accordion(acts, context, &block), class: "clear-both"
-
end
-
-
1
view :bridge_act, cache: :never do
-
opts = act_listing_opts_from_params(nil)
-
act = act_from_context
-
ar = act_renderer(:bridge).new(self, act, opts)
-
class_up "action-list", "my-3"
-
wrap_with_overlay title: ar.overlay_title, slot: breadcrumb_data("History") do
-
act_listing(act, opts[:act_seq], :bridge)
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-history/set/all/history_bridge.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (Attachment)
-
#
-
1
module Attachment;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment.rb"; end
-
1
attr_writer :empty_ok
-
-
1
def self.included host_class
-
2
host_class.extend CarrierWave::CardMount
-
end
-
-
1
event :select_file_revision, after: :select_action do
-
attachment.retrieve_from_store!(attachment.identifier)
-
end
-
-
# we need a card id for the path so we have to update db_content when we have
-
# an id
-
4
event :correct_identifier, :finalize, on: :create, when: proc { |c| !c.web? } do
-
3
update_column(:db_content, attachment.db_content)
-
3
expire
-
end
-
-
1
event :save_original_filename, :prepare_to_store, on: :save, when: :file_ready_to_save? do
-
3
return unless @current_action
-
2
@current_action.update! comment: original_filename
-
end
-
-
1
event :validate_file_exist, :validate, on: :create do
-
3
return if empty_ok?
-
3
if will_be_stored_as == :web
-
errors.add "url is missing" if content.blank?
-
3
elsif !attachment.file.present?
-
errors.add attachment_name, "is missing"
-
end
-
end
-
-
4
event :write_identifier, after: :save_original_filename, when: proc { |c| !c.web? } do
-
3
self.content = attachment.db_content
-
end
-
-
1
def file_ready_to_save?
-
3
attachment.file.present? &&
-
!preliminary_upload? &&
-
!save_preliminary_upload? &&
-
attachment_is_changing?
-
end
-
-
1
def item_names _args={} # needed for flexmail attachments. hacky.
-
[name]
-
end
-
-
1
def original_filename
-
2
return content.split("/").last if web?
-
2
attachment.original_filename
-
end
-
-
1
def unfilled?
-
!attachment.present? && !save_preliminary_upload? && !subcards? && blank_content?
-
end
-
-
1
def attachment_changed?
-
send "#{attachment_name}_changed?"
-
end
-
-
1
def attachment_is_changing?
-
3
send "#{attachment_name}_is_changing?"
-
end
-
-
1
def attachment_before_act
-
send "#{attachment_name}_before_act"
-
end
-
-
1
def create_versions? _new_file
-
true
-
end
-
-
1
def empty_ok?
-
3
@empty_ok
-
end
-
-
1
def assign_set_specific_attributes
-
# reset content if we really have something to upload
-
199
self.content = nil if set_specific[attachment_name.to_s].present?
-
199
super
-
end
-
-
1
def delete_files_for_action action
-
with_selected_action_id(action.id) do
-
attachment.file.delete
-
attachment.versions.each_value do |version|
-
version.file.delete
-
end
-
end
-
end
-
-
1
def revision action, before_action=false
-
return unless (result = super)
-
result[:empty_ok] = true
-
result
-
end
-
-
1
def attachment_format ext
-
1
if ext.present? && attachment && (original_ext = attachment.extension.sub(/^\./, ""))
-
1
if ["file", original_ext].member? ext
-
1
original_ext
-
elsif (exts = Mime::Types[attachment.content_type])
-
if exts.find { |mt| mt.extensions.member? ext }
-
ext
-
else
-
exts[0].extensions[0]
-
end
-
end
-
end
-
rescue => e
-
Rails.logger.info "attachment_format issue: #{e.message}"
-
nil
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Attachment;
-
# Set: Abstract (Attachment, Cloud)
-
#
-
1
module Cloud;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/cloud.rb"; end
-
1
event :change_bucket_if_read_only, :initialize,
-
on: :update, when: :change_bucket_if_read_only? do
-
@new_storage_type = storage_type_from_config
-
end
-
-
1
event :validate_storage_type_update, :validate, on: :update, when: :cloud? do
-
# FIXME: make it possible to retrieve the file from cloud storage
-
# to store it somewhere else. Currently, it only works to change the
-
# storage type if a new file is provided
-
# i.e. `update storage_type: :local` fails but
-
# `update storage_type: :local, file: [file handle]` is ok
-
return unless storage_type_changed? && !attachment_is_changing?
-
-
errors.add :storage_type, tr(:moving_files_is_not_supported)
-
end
-
-
1
def bucket
-
76
@bucket ||= cloud? && (new_card_bucket || bucket_from_content || bucket_from_config)
-
end
-
-
1
def new_card_bucket
-
return unless new_card?
-
# If the file is assigned before the bucket option we have to
-
# check if there is a bucket options in set_specific.
-
# That happens for exmaple when the file appears before the bucket in the
-
# options hash:
-
# Card.create file: file_handle, bucket: "my_bucket"
-
set_specific[:bucket] || set_specific["bucket"] || bucket_from_config
-
end
-
-
1
def bucket_config
-
@bucket_config ||= load_bucket_config
-
end
-
-
1
def load_bucket_config
-
return {} unless bucket
-
bucket_config = Cardio.config.file_buckets&.dig(bucket.to_sym) || {}
-
bucket_config.symbolize_keys!
-
bucket_config[:credentials]&.symbolize_keys!
-
# we don't want :attributes hash symbolized, so we can't use
-
# deep_symbolize_keys
-
ensure_bucket_config do
-
load_bucket_config_from_env bucket_config
-
end
-
end
-
-
1
def ensure_bucket_config
-
yield.tap do |config|
-
require_configuration! config
-
require_credentials! config
-
end
-
end
-
-
1
def require_configuration! config
-
cant_find_in_bucket! "configuration" unless config.present?
-
end
-
-
1
def require_credentials! config
-
cant_find_in_bucket! "credentials" unless config[:credentials]
-
end
-
-
1
def cant_find_in_bucket! need
-
raise Card::Error, "couldn't find #{need} for bucket #{bucket}"
-
end
-
-
1
def load_bucket_config_from_env config
-
config ||= {}
-
each_config_option_from_env do |key|
-
replace_with_env_variable config, key
-
end
-
credential_config config do |cred_hash|
-
load_bucket_credentials_from_env cred_hash
-
end
-
end
-
-
1
def credential_config config
-
config[:credentials] ||= {}
-
yield config[:credentials]
-
config.delete :credentials if config[:credentials].blank?
-
config
-
end
-
-
1
def each_config_option_from_env
-
CarrierWave::FileCardUploader::CONFIG_OPTIONS.each do |key|
-
yield key unless key.in? %i[attributes credentials]
-
end
-
end
-
-
1
def load_bucket_credentials_from_env cred_config
-
each_credential_from_env do |option|
-
replace_with_env_variable cred_config, option, "credentials"
-
end
-
end
-
-
1
def each_credential_from_env
-
regexp = credential_from_env_regexp
-
ENV.each_key do |env_key|
-
next unless (m = regexp.match env_key)
-
yield m[:option].downcase.to_sym
-
end
-
end
-
-
1
def credential_from_env_regexp
-
Regexp.new "^(?:#{bucket.to_s.upcase}_)?CREDENTIALS_(?<option>.+)$"
-
end
-
-
1
def replace_with_env_variable config, option, prefix=nil
-
env_key = [prefix, option].compact.join("_").upcase
-
new_value = ENV["#{bucket.to_s.upcase}_#{env_key}"] || ENV[env_key]
-
config[option] = new_value if new_value
-
end
-
-
1
def bucket_from_content
-
return unless content
-
content.match(/^\((?<bucket>[^)]+)\)/) { |m| m[:bucket] }
-
end
-
-
1
def bucket_from_config
-
cnf = Cardio.config
-
cnf.file_default_bucket || cnf.file_buckets&.keys&.first
-
end
-
-
1
def change_bucket_if_read_only?
-
cloud? && bucket_config[:read_only] && attachment_is_changing?
-
end
-
-
1
def bucket= value
-
if @action == :update
-
@new_bucket = value
-
else
-
@bucket = value
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/cloud.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Attachment;
-
# Set: Abstract (Attachment, Coded)
-
#
-
1
module Coded;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/coded.rb"; end
-
1
event :lose_coded_status_on_update, :initialize, on: :update, when: :coded? do
-
# unless explicit
-
return if @new_mod
-
@new_storage_type ||= storage_type_from_config
-
end
-
-
1
event :validate_coded_storage_type, :validate, on: :save, when: :will_become_coded? do
-
errors.add :storage_type, tr(:mod_argument_needed_to_save) unless mod || @new_mod
-
errors.add :storage_type, tr(:codename_needed_for_storage) if codename.blank?
-
end
-
-
1
def will_become_coded?
-
14
will_be_stored_as == :coded
-
end
-
-
1
def mod= value
-
if @action == :update && mod != value
-
@new_mod = value.to_s
-
else
-
@mod = value.to_s
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/coded.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Attachment;
-
# Set: Abstract (Attachment, Local)
-
#
-
1
module Local;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/local.rb"; end
-
-
1
event :update_public_link_on_create, :integrate, on: :create, when: :local? do
-
3
update_public_link
-
end
-
-
1
event :remove_public_link_on_delete, :integrate, on: :delete, when: :local? do
-
remove_public_links
-
end
-
-
1
event :update_public_link, after: :update_read_rule, when: :local? do
-
5
return if content.blank?
-
5
if who_can(:read).include? Card::AnyoneID
-
3
create_public_links
-
else
-
2
remove_public_links
-
end
-
end
-
-
1
private
-
-
1
def create_public_links
-
3
path = attachment.public_path
-
3
return if File.exist? path
-
3
FileUtils.mkdir_p File.dirname(path)
-
3
File.symlink attachment.path, path unless File.symlink? path
-
3
create_versions_public_links
-
end
-
-
1
def create_versions_public_links
-
3
attachment.versions.each_value do |version|
-
8
next if File.symlink? version.public_path
-
8
File.symlink version.path, version.public_path
-
end
-
end
-
-
1
def remove_public_links
-
2
symlink_dir = File.dirname attachment.public_path
-
2
return unless Dir.exist? symlink_dir
-
2
FileUtils.rm_rf symlink_dir
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/local.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Attachment;
-
# Set: Abstract (Attachment, Paths)
-
#
-
1
module Paths;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/paths.rb"; end
-
1
MOD_FILE_DIR = "file".freeze
-
-
1
def store_dir
-
11
will_become_coded? ? coded_dir(@new_mod) : upload_dir
-
end
-
-
1
def retrieve_dir
-
232
coded? ? coded_dir : upload_dir
-
end
-
-
# place for files of regular file cards
-
1
def upload_dir
-
34
id ? "#{files_base_dir}/#{id}" : tmp_upload_dir
-
end
-
-
# place for files of mod file cards
-
1
def coded_dir new_mod=nil
-
209
dir = File.join mod_dir(new_mod), MOD_FILE_DIR, codename.to_s
-
209
FileUtils.mkdir_p(dir) unless File.directory?(dir)
-
209
dir
-
end
-
-
1
def mod_dir new_mod=nil
-
209
mod_name = new_mod || mod
-
209
dir = Mod.dirs.path(mod_name) || (mod_name.to_sym == :test && "test")
-
-
209
raise Error, "can't find mod \"#{mod_name}\"" unless dir
-
209
dir
-
end
-
-
1
def files_base_dir
-
76
dir = bucket ? bucket_config[:subdirectory] : Card.paths["files"].existent.first
-
76
dir || files_base_dir_configuration_error
-
end
-
-
1
def files_base_dir_configuration_error
-
raise StandardError,
-
"missing directory for file cache (default is `files` in deck root)"
-
end
-
-
# used in the indentifier
-
1
def file_dir
-
147
if coded?
-
116
":#{codename}"
-
31
elsif cloud?
-
"(#{bucket})/#{file_id}"
-
else
-
31
"~#{file_id}"
-
end
-
end
-
-
1
def public?
-
who_can(:read).include? Card::AnyoneID
-
end
-
-
1
def file_id
-
31
id? ? id : upload_cache_card.id
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/paths.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Attachment;
-
# Set: Abstract (Attachment, StorageType)
-
#
-
1
module StorageType;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/storage_type.rb"; end
-
1
attr_writer :bucket, :storage_type
-
-
1
event :storage_type_change, :store, on: :update, when: :storage_type_changed? do
-
# carrierwave stores file if @cache_id is not nil
-
attachment.cache_stored_file!
-
# attachment.retrieve_from_cache!(attachment.cache_name)
-
update_storage_attributes
-
# next line might be necessary to move files to cloud
-
-
# make sure that we get the new identifier
-
# otherwise action_id will return wrong id for new identifier
-
db_content_will_change!
-
write_identifier
-
end
-
-
1
event :validate_storage_type, :validate, on: :save do
-
3
unless known_storage_type? will_be_stored_as
-
errors.add :storage_type, tr(
-
:unknown_storage_type,
-
new_storage_type: @new_storage_type
-
)
-
end
-
end
-
-
1
def will_be_stored_as
-
20
@new_storage_type || storage_type
-
end
-
-
1
def read_only?
-
web? || (cloud? && bucket_config[:read_only])
-
end
-
-
1
def cloud?
-
249
storage_type == :cloud
-
end
-
-
1
def web?
-
188
storage_type == :web
-
end
-
-
1
def local?
-
6
storage_type == :local
-
end
-
-
1
def coded?
-
891
storage_type == :coded
-
end
-
-
1
def remote_storage?
-
1
cloud? || web?
-
end
-
-
1
def storage_type
-
1597
@storage_type ||=
-
127
new_card? ? storage_type_from_config : storage_type_from_content
-
end
-
-
1
def deprecated_mod_file?
-
content && (lines = content.split("\n")) && lines.size == 4
-
end
-
-
1
def mod
-
325
@mod ||= coded? && mod_from_content
-
end
-
-
1
def mod_from_content
-
117
if content =~ %r{^:[^/]+/([^.]+)}
-
117
Regexp.last_match(1) # current mod_file format
-
else
-
mod_from_deprecated_content
-
end
-
end
-
-
# old format is still used in card_changes
-
1
def mod_from_deprecated_content
-
return if content =~ /^\~/
-
return unless (lines = content.split("\n")) && lines.size == 4
-
lines.last
-
end
-
-
1
def storage_type_from_config
-
3
valid_storage_type ENV["FILE_STORAGE"] || Cardio.config.file_storage
-
end
-
-
1
def valid_storage_type storage_type
-
3
storage_type.to_sym.tap do |type|
-
3
invalid_storage_type! type unless type.in? valid_storage_type_list
-
end
-
end
-
-
1
def valid_storage_type_list
-
3
CarrierWave::FileCardUploader::STORAGE_TYPES
-
end
-
-
1
def invalid_storage_type! type
-
raise Card::Error, tr(:error_invalid_storage_type, type: type)
-
end
-
-
1
def storage_type_from_content
-
124
case content
-
when /^\(/ then :cloud
-
when %r{/^https?\:/} then :web
-
7
when /^~/ then :local
-
117
when /^\:/ then :coded
-
else
-
if deprecated_mod_file?
-
:coded
-
else
-
storage_type_from_config
-
end
-
end
-
end
-
-
1
def update_storage_attributes
-
@mod = @new_mod if @new_mod
-
@bucket = @new_bucket if @new_bucket
-
@storage_type = @new_storage_type
-
end
-
-
1
def storage_type_changed?
-
@new_bucket || (@new_storage_type && @new_storage_type != storage_type) || @new_mod
-
end
-
-
1
def storage_type= value
-
known_storage_type? value
-
if @action == :update #&& storage_type != value
-
# we cant update the storage type directly here
-
# if we do then the uploader doesn't find the file we want to update
-
@new_storage_type = value
-
else
-
@storage_type = value
-
end
-
end
-
-
1
def with_storage_options opts={}
-
153
old_values = {}
-
153
validate_temporary_storage_type_change opts[:storage_type]
-
153
%i[storage_type mod bucket].each do |opt_name|
-
459
next unless opts[opt_name]
-
old_values[opt_name] = instance_variable_get "@#{opt_name}"
-
instance_variable_set "@#{opt_name}", opts[opt_name]
-
@temp_storage_type = true
-
end
-
153
yield
-
ensure
-
153
@temp_storage_type = false
-
153
old_values.each do |key, val|
-
instance_variable_set "@#{key}", val
-
end
-
end
-
-
1
def temporary_storage_type_change?
-
127
@temp_storage_type
-
end
-
-
1
def validate_temporary_storage_type_change new_storage_type=nil
-
153
new_storage_type ||= @new_storage_type
-
153
return unless new_storage_type
-
unless known_storage_type? new_storage_type
-
raise Error, tr(:unknown_storage_type, new_storage_type: new_storage_type)
-
end
-
-
if new_storage_type == :coded && codename.blank?
-
raise Error, "codename needed for storage type :coded"
-
end
-
end
-
-
1
def known_storage_type? type=storage_type
-
3
type.in? CarrierWave::FileCardUploader::STORAGE_TYPES
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/storage_type.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Attachment;
-
# Set: Abstract (Attachment, UploadCache)
-
#
-
# action id of the cached upload
-
1
module UploadCache;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/upload_cache.rb"; end
-
1
attr_accessor :action_id_of_cached_upload
-
-
1
def actionable?
-
8
super || preliminary_upload?
-
end
-
-
1
event :prepare_attachment, :prepare_to_validate, on: :save, when: :preliminary_upload? do
-
save_original_filename # save original filename as comment in action
-
write_identifier # set db_content
-
# (needs original filename to determine extension)
-
store_attachment!
-
store_card_changes
-
# finalize_action # create Card::Change entry for db_content
-
-
card_id = new_card? ? upload_cache_card.id : id
-
@current_action.update! draft: true, card_id: card_id
-
success << {
-
target: (new_card? ? upload_cache_card : self),
-
type: type_name,
-
view: "preview_editor",
-
rev_id: current_action.id
-
}
-
abort :success
-
end
-
-
1
event :assign_attachment_on_create, :initialize,
-
after: :assign_action, on: :create, when: :save_preliminary_upload? do
-
return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
-
upload_cache_card.selected_action_id = action.id
-
upload_cache_card.select_file_revision
-
assign_attachment upload_cache_card.attachment.file, action.comment
-
end
-
-
1
event :assign_attachment_on_update, :initialize,
-
after: :assign_action, on: :update, when: :save_preliminary_upload? do
-
return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
-
uploaded_file = with_selected_action_id(action.id) { attachment.file }
-
assign_attachment uploaded_file, action.comment
-
end
-
-
1
def assign_attachment file, original_filename
-
send "#{attachment_name}=", file
-
write_identifier
-
@current_action&.update! comment: original_filename
-
end
-
-
1
event :delete_cached_upload_file_on_create, :integrate,
-
on: :create, when: :save_preliminary_upload? do
-
return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
-
upload_cache_card.delete_files_for_action action
-
action.delete
-
end
-
-
# at some point uploaded files of canceled file card creation
-
# should be deleted. We do this when ever an new file is created.
-
1
event :clear_draft_files, :integrate_with_delay, priority: 100, on: :create do
-
3
Card.delete_tmp_files_of_cached_uploads
-
end
-
-
1
event :delete_cached_upload_file_on_update, :integrate,
-
on: :update, when: :save_preliminary_upload? do
-
return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
-
delete_files_for_action action
-
action.delete
-
end
-
-
# used for uploads for new cards until the new card is created
-
1
def upload_cache_card
-
2
cache_card_codename = "new_#{attachment_name}"
-
2
@upload_cache_card ||= Card::Codename.card(cache_card_codename) { Card[:new_file] }
-
end
-
-
1
def preliminary_upload?
-
10
Card::Env && Card::Env.params[:attachment_upload]
-
end
-
-
1
def save_preliminary_upload?
-
8
@action_id_of_cached_upload.present?
-
end
-
-
# place for files if card doesn't have an id yet
-
1
def tmp_upload_dir _action_id=nil
-
"#{files_base_dir}/#{upload_cache_card.id}"
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/upload_cache.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Abstract; module Attachment;
-
# Set: Abstract (Attachment, Web)
-
#
-
1
module Web;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/web.rb"; end
-
1
def no_upload?
-
web? || storage_type_from_config == :web
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/abstract/attachment/web.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (FileUtils)
-
#
-
1
module FileUtils;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/all/file_utils.rb"; end
-
1
module ClassMethods
-
1
def update_all_storage_locations
-
Card.search(type_id: ["in", Card::FileID, Card::ImageID])
-
.each(&:update_storage_location!)
-
end
-
-
1
def delete_tmp_files_of_cached_uploads
-
3
cards_with_disposable_attachments do |card, action|
-
card.delete_files_for_action action
-
action.delete
-
end
-
end
-
-
1
def cards_with_disposable_attachments
-
3
draft_actions_with_attachment.each do |action|
-
# we don't want to delete uploads in progress
-
next unless old_enough?(action.created_at) && (card = action.card)
-
# we can't delete attachments we don't have write access to
-
next if card.read_only?
-
-
yield card, action
-
end
-
end
-
-
1
def old_enough? time, expiration_time=5.day.to_i
-
Time.now - time > expiration_time
-
end
-
-
1
def draft_actions_with_attachment
-
3
Card::Action.find_by_sql(
-
"SELECT * FROM card_actions "\
-
"INNER JOIN cards ON card_actions.card_id = cards.id "\
-
"WHERE cards.type_id IN (#{Card::FileID}, #{Card::ImageID}) "\
-
"AND card_actions.draft = true"
-
)
-
end
-
-
1
def count_cards_with_attachment
-
Card.search type_id: ["in", Card::FileID, Card::ImageID], return: :count
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/all/file_utils.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Admin"
-
#
-
1
module Admin;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/admin.rb"; end
-
1
add_to_basket(
-
:tasks,
-
name: :update_file_storage_locations,
-
execute_policy: -> { Card.update_all_storage_locations },
-
stats: {
-
title: "cards with attachment",
-
count: -> { Card.count_cards_with_attachment }
-
# link_text: "update storage locations",
-
# task: "update_file_storage_locations"
-
}
-
)
-
-
1
add_to_basket(
-
:tasks,
-
name: :delete_upload_tmp_files,
-
execute_policy: -> { Card.delete_tmp_files_of_cached_uploads },
-
stats: {
-
title: "tmp files of canceled uploads",
-
count: -> { ::Card.draft_actions_with_attachment },
-
link_text: "delete tmp files",
-
task: "delete_tmp_files_of_cached_uploads"
-
}
-
)
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/admin.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Favicon"
-
#
-
1
module Favicon;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/favicon.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :source do
-
23
source = card.type_id == Card::ImageID ? super() : nil
-
23
source.present? ? source : nest(:logo, view: :source, size: voo.size)
-
end
-
-
1
view :link_tag, perms: :none do
-
23
return unless (source = render :source, size: :small)
-
23
tag :link, rel: "shortcut icon", href: source
-
end
-
-
1
def raw_help_text
-
"A favicon (or shortcut icon) is a small image used by browsers to help identify "\
-
"your website. [[http://www.decko.org/favicon|How to customize your favicon]]"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/favicon.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "NewFile"
-
#
-
1
module NewFile;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/new_file.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :source, cache: :never do
-
super()
-
end
-
-
1
view :core, cache: :never do
-
super()
-
end
-
-
1
view :input, cache: :never do
-
super()
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/new_file.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "NewImage"
-
#
-
1
module NewImage;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/new_image.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :source, cache: :never do
-
super()
-
end
-
-
1
view :core, cache: :never do
-
super()
-
end
-
-
1
view :input, cache: :never do
-
super()
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/self/new_image.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "File" cards
-
#
-
1
module File;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/type/file.rb"; end
-
1
attachment :file, uploader: CarrierWave::FileCardUploader
-
-
1
module SelectedAction
-
1
def select_action_by_params params
-
# skip action table lookups for current revision
-
7
rev_id = params[:rev_id]
-
7
super unless rev_id && rev_id == last_content_action_id
-
end
-
-
1
def last_content_action_id
-
127
return super if temporary_storage_type_change?
-
# find action id from content (saves lookups)
-
127
db_content.to_s.split(%r{[/\.]})[-2]
-
end
-
end
-
1
include SelectedAction
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :source do
-
1
file = card.attachment
-
1
return "" unless file.valid?
-
1
contextualize_path file.url
-
end
-
-
1
view :core do
-
1
handle_source do |source|
-
1
card_url source
-
end
-
end
-
-
1
def short_content
-
number_to_human_size card.attachment.size
-
end
-
-
1
def handle_source
-
3
source = _render_source
-
3
return "" if source.blank?
-
3
block_given? ? yield(source) : source
-
rescue => e
-
Rails.logger.info "Error with file source: #{e.message}"
-
tr :file_error
-
end
-
-
1
def selected_version
-
1
card.attachment
-
end
-
end
-
-
2
module FileFormat; module_parent.send :register_set_format, Card::Format::FileFormat, self; extend Card::Set::AbstractFormat
-
# NOCACHE because returns send_file args. not in love with this...
-
1
view :core, cache: :never do
-
# this means we only support known formats. dislike.
-
1
attachment_format = card.attachment_format(params[:format])
-
1
return _render_not_found unless attachment_format
-
1
return card.format(:html).render_core if card.remote_storage?
-
1
set_response_headers
-
1
args_for_send_file
-
end
-
-
1
def args_for_send_file
-
1
file = selected_version
-
1
[file.path, { type: file.content_type,
-
filename: "#{card.name.safe_key}#{file.extension}",
-
x_sendfile: true,
-
1
disposition: (params[:format] == "file" ? "attachment" : "inline") }]
-
end
-
-
1
def set_response_headers
-
1
return unless params[:explicit_file] && (response = controller&.response)
-
1
response.headers["Expires"] = 1.year.from_now.httpdate
-
# currently using default "private", because proxy servers could block
-
# needed permission checks
-
# r.headers["Cache-Control"] = "public"
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
handle_source do |source|
-
"<a href=\"#{source}\">#{tr :download, title: title_in_context(voo.title)}</a>"
-
end
-
end
-
-
1
view :input do
-
if card.no_upload?
-
text_field :content, class: "d0-card-content"
-
else
-
haml :file_chooser, action_text: file_chooser_action_text
-
end
-
end
-
-
1
view :preview_editor, unknown: true, cache: :never do
-
haml :preview_editor
-
end
-
-
1
def file_chooser_action_text
-
action = card.new_card? ? "Add" : "Replace"
-
"#{action} #{humanized_attachment_name}..."
-
end
-
-
1
def humanized_attachment_name
-
card.attachment_name.to_s.humanize
-
end
-
-
1
def preview
-
""
-
end
-
-
1
def cached_upload_card_name
-
Card::Env.params[:attachment_upload].gsub(/\[\w+\]$/, "[action_id_of_cached_upload]")
-
end
-
-
1
def preview_editor_delete_text
-
tr :delete
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/type/file.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Image" cards
-
#
-
1
module Image;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/type/image.rb"; end
-
1
attachment :image, uploader: CarrierWave::ImageCardUploader
-
-
1
include File::SelectedAction
-
-
1
def create_versions? new_file
-
256
new_file.extension != "svg"
-
end
-
-
1
def svg?
-
25
image&.extension == ".svg"
-
end
-
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
include File::Format
-
-
1
view :one_line_content do
-
_render_core size: :icon
-
end
-
-
1
def short_content
-
2
render_core size: :icon
-
end
-
-
1
view :source do
-
25
return card.content if card.web?
-
25
image = selected_version
-
25
return "" unless image.valid?
-
25
contextualize_path image.url
-
end
-
-
1
def selected_version
-
25
size = determine_image_size
-
25
if size && size != :original
-
25
card.image.versions[size]
-
else
-
card.image
-
end
-
end
-
-
1
def handle_source
-
2
super
-
end
-
-
1
def closed_size
-
:icon
-
end
-
-
1
def main_size
-
:large
-
end
-
-
1
def default_size
-
:medium
-
end
-
-
1
def determine_image_size
-
25
voo.size =
-
case
-
when nest_mode == :closed then closed_size
-
25
when voo.size.present? then voo.size.to_sym
-
when main? then main_size
-
else default_size
-
end
-
25
voo.size = :original if voo.size == :full
-
25
voo.size
-
end
-
-
1
view :inline do
-
_render_core
-
end
-
end
-
-
2
module EmailHtmlFormat; module_parent.send :register_set_format, Card::Format::EmailHtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :inline, cache: :never do
-
handle_source do |source|
-
return source unless (mail = inherit :active_mail) &&
-
::File.exist?(path = selected_version.path)
-
url = attach_image mail, path
-
image_tag url
-
end
-
end
-
-
1
def attach_image mail, path
-
mail.attachments.inline[path] = ::File.read path
-
mail.attachments[path].url
-
end
-
end
-
-
2
module CssFormat; module_parent.send :register_set_format, Card::Format::CssFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
handle_source
-
end
-
-
1
view :content do # why is this necessary?
-
render_core
-
end
-
end
-
-
2
module FileFormat; module_parent.send :register_set_format, Card::Format::FileFormat, self; extend Card::Set::AbstractFormat
-
1
include File::FileFormat
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/type/image.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Type; module Image;
-
# Set: All "Image+HtmlViews" cards (HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/type/image/html_views.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
include File::HtmlFormat
-
-
# core HTML image view.
-
1
view :core do
-
25
return card.attachment.read if card.svg?
-
2
with_valid_source do |source|
-
2
image_tag source, alt: card.name
-
end
-
end
-
-
1
def with_valid_source
-
2
handle_source do |source|
-
2
if source.blank? || source == "missing"
-
# FIXME: these images should be "broken", not "missing"
-
invalid_image source
-
else
-
2
yield source
-
# consider title..
-
end
-
end
-
end
-
-
1
view :full_width do
-
with_valid_source do |source|
-
image_tag source, alt: card.name, class: "w-100"
-
end
-
end
-
-
1
def invalid_image source
-
# ("missing" is the view for "unknown" now, so we shouldn't further confuse things)
-
"<!-- invalid image for #{safe_name}; source: #{source} -->"
-
end
-
-
1
def preview
-
return if card.new_card? && !card.preliminary_upload?
-
wrap_with :div, class: "attachment-preview",
-
id: "#{card.attachment.filename}-preview" do
-
_render_core size: :medium
-
end
-
end
-
-
1
def show_action_content_toggle? _action, _view_type
-
true
-
end
-
-
1
view :content_changes do
-
content_changes card.last_action, :expanded
-
end
-
-
1
def content_changes action, diff_type, hide_diff=false
-
voo.size = diff_type == :summary ? :icon : :medium
-
[old_image(action, hide_diff), new_image(action)].compact.join
-
end
-
-
1
def old_image action, hide_diff
-
return if hide_diff || !action
-
return unless (last_change = card.last_change_on(:db_content, before: action))
-
card.with_selected_action_id last_change.card_action_id do
-
Card::Content::Diff.render_deleted_chunk _render_core
-
end
-
end
-
-
1
def new_image action
-
card.with_selected_action_id action.id do
-
Card::Content::Diff.render_added_chunk _render_core
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-carrierwave/set/type/image/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Calendar)
-
#
-
1
module Calendar;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-date/set/all/calendar.rb"; end
-
1
Self::InputOptions.add_to_basket :options, "calendar"
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def calendar_input
-
1
text_field :content, class: "date-editor datetimepicker-input",
-
"data-toggle": "datetimepicker",
-
"data-target": "##{form_prefix}_content.date-editor"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-date/set/all/calendar.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Datepicker"
-
#
-
1
module Datepicker;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-date/set/self/datepicker.rb"; end
-
1
def raw_help_text
-
<<-TEXT
-
Configure the date select tool using these available
-
[[https://tempusdominus.github.io/bootstrap-4/Options/|options]]
-
TEXT
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-date/set/self/datepicker.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptDatepicker"
-
#
-
1
module ScriptDatepicker;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-date/set/self/script_datepicker.rb"; end
-
1
include_set Abstract::VendorCodeFile
-
1
Self::ScriptMods.add_item :script_datepicker
-
-
1
def source_files
-
%w[moment/min/moment-with-locales.min.js
-
tempusdominus/build/js/tempusdominus-bootstrap-4.js]
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-date/set/self/script_datepicker.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptDatepickerConfig"
-
#
-
1
module ScriptDatepickerConfig;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-date/set/self/script_datepicker_config.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptEditors.add_item :script_datepicker_config
-
1
All::Head::HtmlFormat.add_to_basket :mod_js_config, [:datepicker, "setDatepickerConfig"]
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-date/set/self/script_datepicker_config.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleDatepicker"
-
#
-
1
module StyleDatepicker;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-date/set/self/style_datepicker.rb"; end
-
1
include_set Abstract::CodeFile
-
1
Self::StyleLibraries.add_item :style_datepicker
-
-
1
def source_files
-
2
%w[lib/stylesheets/tempusdominus.scss
-
vendor/tempusdominus/src/sass/_tempusdominus-bootstrap-4.scss]
-
end
-
-
1
def source_dir
-
4
""
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-date/set/self/style_datepicker.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Date" cards
-
#
-
1
module Date;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-date/set/type/date.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def input_type
-
1
:calendar
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-date/set/type/date.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Abstract
-
# Set: Abstract (FollowOption)
-
#
-
1
module FollowOption;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/abstract/follow_option.rb"; end
-
1
def restrictive_option?
-
Card::FollowOption.restrictive_options.include? codename
-
end
-
-
1
def description set_card
-
4
set_card.follow_label
-
end
-
-
# follow option methods on the Card class
-
# FIXME: there's not a great reason to have these on the Card class
-
1
module ClassMethods
-
# args:
-
# position: <Fixnum> (starting at 1, default: add to end)
-
1
def restrictive_follow_opts args
-
2
add_option args, :restrictive
-
end
-
-
# args:
-
# position: <Fixnum> (starting at 1, default: add to end)
-
1
def follow_opts args
-
2
add_option args, :main
-
end
-
-
1
def follow_test opts={}, &block
-
2
Card::FollowOption.test[get_codename(opts)] = block
-
end
-
-
1
def follower_candidate_ids opts={}, &block
-
2
Card::FollowOption.follower_candidate_ids[get_codename(opts)] = block
-
end
-
-
1
private
-
-
1
def insert_option pos, item, type
-
4
list = Card::FollowOption.codenames(type)
-
4
list[pos] ? list.insert(pos, item) : (list[pos] = item)
-
# If pos > codenames.size in a previous insert then we have a bunch
-
# of preceding nils in the array.
-
# Hence, we have to overwrite a nil value if we encounter one and
-
# can't use insert.
-
end
-
-
1
def add_option opts, type, &_block
-
4
codename = get_codename opts
-
4
if opts[:position]
-
4
insert_option opts[:position] - 1, codename, type
-
else
-
Card::FollowOption.codenames(type) << codename
-
end
-
4
Card::FollowOption.codenames(:all) << codename
-
end
-
-
1
def get_codename opts
-
8
opts[:codename] || name.match(/::(\w+)$/)[1].underscore.to_sym
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/abstract/follow_option.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Follow)
-
#
-
# for override
-
1
module Follow;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow.rb"; end
-
1
def followable?
-
14
true
-
end
-
-
1
def follow_label
-
name
-
end
-
-
1
def list_direct_followers?
-
false
-
end
-
-
1
def follow_option?
-
codename && FollowOption.codenames.include?(codename)
-
end
-
-
# the set card to be followed if you want to follow changes of card
-
1
def follow_set_card
-
Card.fetch name, :self
-
end
-
-
1
def follow_rule_name user=nil
-
follow_set_card&.follow_rule_name user
-
end
-
-
1
def follow_rule_card user=nil, args={}
-
Card.fetch follow_rule_name(user), args
-
end
-
-
1
def follow_rule? user=nil
-
Card.exists? follow_rule_name(user)
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Follow)
-
#
-
#! no set module
-
1
module Follow;
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/follow_link.rb"; end
-
1
class FollowLink
-
1
attr_reader :format, :rule_content, :link_text, :action, :css_class, :hover_text
-
-
1
delegate :link_to, to: :format
-
-
1
def initialize format
-
@format = format
-
@card = format.card
-
end
-
-
1
def modal_link icon=false
-
opts = link_opts.merge(
-
"data-path": link_opts[:path],
-
"data-toggle": "modal",
-
"data-target": "#modal-#{card.name.safe_key}",
-
class: css_classes("follow-link", link_opts[:class])
-
)
-
link_to render_link_text(icon), opts
-
end
-
-
1
def button
-
opts = link_opts(:follow_section).merge(
-
remote: true,
-
class: @format.css_classes("follow-link", link_opts[:class],
-
"slotter btn btn-sm btn-primary")
-
)
-
opts["data-update-foreign-slot"] = ".d0-card-body > .card-slot.RIGHT-Xfollower.content-view"
-
opts["data-hover-text"] = hover_text if hover_text
-
link_to render_link_text, opts
-
end
-
-
1
def link_opts success_view=:follow_status
-
{ title: title,
-
path: path(success_view),
-
class: css_class }
-
end
-
-
1
def render_link_text icon=false
-
verb = %(<span class="follow-verb">#{link_text}</span>)
-
icon = icon ? icon_tag(:flag) : ""
-
[icon, verb].compact.join.html_safe
-
end
-
-
1
private
-
-
1
def mark
-
@card.follow_set_card.follow_rule_name Auth.current.name
-
end
-
-
1
def path view=:follow_status
-
@format.path mark: mark,
-
action: :update,
-
success: { id: @card.name, view: view },
-
card: { content: "[[#{rule_content}]]" }
-
end
-
-
1
def title
-
"#{action} emails about changes to #{@card.follow_label}"
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/follow_link.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Follow;
-
# Set: All cards (Follow, FollowLinkViews)
-
#
-
1
module FollowLinkViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/follow_link_views.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
def follow_link_class
-
card.followed? ? StopFollowLink : StartFollowLink
-
end
-
-
1
def show_follow?
-
1
Auth.signed_in? && !card.new_card? && card.followable?
-
end
-
end
-
-
2
module JsonFormat; module_parent.send :register_set_format, Card::Format::JsonFormat, self; extend Card::Set::AbstractFormat
-
1
view :follow_status do
-
follow_link_class.link_opts
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def follow_button
-
follow_link_class.new(self).button
-
end
-
-
1
def follow_modal_link
-
follow_link_class.new(self).modal_link
-
end
-
-
1
view :follow_button, cache: :never do
-
follow_button
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/follow_link_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Follow;
-
# Set: All cards (Follow, FollowedBy)
-
#
-
# used by +:followers overwritten in type/set.rb and type/cardtype.rb
-
1
module FollowedBy;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/followed_by.rb"; end
-
1
def followed?
-
followed_by? Auth.current_id
-
end
-
-
# for sets and cardtypes it doesn't check whether the users is following the
-
# card itself instead it checks whether he is following the complete set
-
1
def followed_by? user_id
-
follow_rule_applies?(user_id) || left&.followed_by_as_field?(self, user_id)
-
end
-
-
1
def followed_by_as_field? field, user_id
-
followed_field?(field) && followed_by?(user_id)
-
end
-
-
# returns true if according to the follow_field_rule followers of self also
-
# follow changes of field_card
-
1
def followed_field? field_card
-
return unless (follow_field_rule = rule_card(:follow_fields))
-
-
follow_field_rule.item_names(context: self).find do |item|
-
case item.to_name.key
-
when field_card.key then true
-
when :nests.cardname.key then nested_card?(field_card)
-
end
-
end
-
end
-
-
1
def nested_card? card
-
nestee_ids.include? card.id
-
end
-
-
## the following methods all handle _explicit_ (direct) follow rules (not fields)
-
-
1
def follow_rule_applies? follower_id
-
!follow_rule_option(follower_id).nil?
-
end
-
-
1
def follow_rule_option follower_id
-
62
all_follow_rule_options(follower_id).find do |option|
-
124
follow_rule_option_applies? follower_id, option
-
end
-
end
-
-
1
def all_follow_rule_options follower_id
-
62
follow_rule = preference :follow, follower_id
-
62
return [] unless follow_rule.present?
-
-
62
follow_rule.split("\n")
-
end
-
-
1
def follow_rule_option_applies? follower_id, option
-
124
option_code = option.to_name.code
-
124
candidate_ids = follower_candidate_ids_for_option option_code
-
124
follow_rule_option_applies_to_candidates? follower_id, option_code, candidate_ids
-
end
-
-
1
def follow_rule_option_applies_to_candidates? follower_id, option_code, candidate_ids
-
124
if (test = FollowOption.test[option_code])
-
test.call follower_id, candidate_ids
-
else
-
124
candidate_ids.include? follower_id
-
end
-
end
-
-
1
def follower_candidate_ids_for_option option_code
-
124
return [] unless (block = FollowOption.follower_candidate_ids[option_code])
-
-
124
block.call self
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/followed_by.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Follow;
-
# Set: All cards (Follow, FollowerIds)
-
#
-
1
module FollowerIds;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/follower_ids.rb"; end
-
1
FOLLOWER_IDS_CACHE_KEY = "FOLLOWER_IDS".freeze
-
-
1
card_accessor :followers
-
-
1
event :cache_expired_for_type_change, :store, on: :update, changed: %i[type_id name] do
-
19
act_card&.schedule_preference_expiration
-
# FIXME: expire (also?) after save
-
19
Card.follow_caches_expired
-
end
-
-
1
def schedule_preference_expiration
-
19
@expire_preferences_scheduled = true
-
end
-
-
1
def expire_preferences?
-
318
@expire_preferences_scheduled
-
end
-
-
1
event :expire_preferences_cache, :finalize, when: :expire_preferences? do
-
14
Card::Rule.clear_preference_cache
-
end
-
-
# follow cache methods on Card class
-
1
module ClassMethods
-
1
def follow_caches_expired
-
28
Card.clear_follower_ids_cache
-
28
Card::Rule.clear_preference_cache
-
end
-
-
1
def follower_ids_cache
-
Card.cache.read(FOLLOWER_IDS_CACHE_KEY) || {}
-
end
-
-
1
def write_follower_ids_cache hash
-
Card.cache.write FOLLOWER_IDS_CACHE_KEY, hash
-
end
-
-
1
def clear_follower_ids_cache
-
28
Card.cache.write FOLLOWER_IDS_CACHE_KEY, nil
-
end
-
end
-
-
1
def write_follower_ids_cache user_ids
-
hash = Card.follower_ids_cache
-
hash[id] = user_ids
-
Card.write_follower_ids_cache hash
-
end
-
-
1
def read_follower_ids_cache
-
Card.follower_ids_cache[id]
-
end
-
-
1
def follower_names
-
followers.map(&:name)
-
end
-
-
1
def followers
-
follower_ids.map do |id|
-
Card.fetch(id)
-
end
-
end
-
-
1
def follower_ids
-
@follower_ids = read_follower_ids_cache || begin
-
result = direct_follower_ids + indirect_follower_ids
-
write_follower_ids_cache result
-
result
-
end
-
end
-
-
1
def followers_count
-
follower_ids.size
-
end
-
-
1
def indirect_follower_ids
-
result = ::Set.new
-
left_card = left
-
while left_card
-
result += left_card.direct_follower_ids if left_card.followed_field? self
-
left_card = left_card.left
-
end
-
result
-
end
-
-
# all users (cards) that "directly" follow this card
-
# "direct" means there is a follow rule that applies explicitly to this card.
-
# one can also "indirectly" follow cards by following parent cards or other
-
# cards that nest this one.
-
1
def direct_followers
-
direct_follower_ids.map do |id|
-
Card.fetch(id)
-
end
-
end
-
-
1
def direct_follower_ids &block
-
31
ids = ::Set.new
-
31
set_names.each do |set_name|
-
153
direct_follower_ids_for_set setcard_from_name(set_name), ids, &block
-
end
-
31
ids
-
end
-
-
1
def setcard_from_name set_name
-
153
Card.fetch set_name, new: { type_id: SetID }
-
end
-
-
1
def direct_follower_ids_for_set set_card, ids
-
153
set_card.all_user_ids_with_rule_for(:follow).each do |user_id|
-
62
next if ids.include?(user_id) || !(option = follow_rule_option user_id)
-
-
yield user_id, set_card, option if block_given?
-
ids << user_id
-
end
-
end
-
-
1
def each_direct_follower_id_with_reason
-
31
direct_follower_ids do |user_id, set_card, follow_option|
-
reason = follow_option.gsub(/[\[\]]/, "")
-
yield user_id, set_card: set_card, option: reason
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/follower_ids.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Follow)
-
#
-
#! no set module
-
1
module Follow;
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/start_follow_link.rb"; end
-
-
1
class StartFollowLink < FollowLink
-
1
def initialize format
-
@rule_content = "*always"
-
@link_text = "follow"
-
@action = "send"
-
@css_class = ""
-
super
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/start_follow_link.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Follow)
-
#
-
#! no set module
-
1
module Follow;
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/stop_follow_link.rb"; end
-
-
1
class StopFollowLink < FollowLink
-
1
def initialize format
-
@rule_content = "*never"
-
@link_text = "following"
-
@hover_text = "unfollow"
-
@action = "stop sending"
-
@css_class = "btn-item-delete"
-
super
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/follow/stop_follow_link.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Notify)
-
#
-
1
module Notify;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/notify.rb"; end
-
1
attr_accessor :follower_stash
-
1
mattr_accessor :force_notifications
-
-
1
event :silence_notifications, :initialize, when: :silence_notifications? do
-
295
@silent_change = true
-
end
-
-
1
def silence_notifications?
-
332
!(Card::Env[:controller] || force_notifications)
-
end
-
-
1
event :notify_followers_after_save,
-
:integrate_with_delay, on: :save, when: :notable_change? do
-
9
notify_followers
-
end
-
-
# in the delete case we have to calculate the follower_stash beforehand
-
# but we can't pass the follower_stash through the ActiveJob queue.
-
# We have to deal with the notifications in the integrate phase instead of the
-
# integrate_with_delay phase
-
1
event :stash_followers, :store, on: :delete, when: :notable_change? do
-
2
act_card.follower_stash ||= FollowerStash.new
-
2
act_card.follower_stash.check_card self
-
end
-
-
1
event :notify_followers_after_delete, :integrate, on: :delete, when: :notable_change? do
-
2
notify_followers
-
end
-
-
1
def notify_followers
-
11
return unless (act = Card::Director.act)
-
-
11
act.reload
-
11
notify_followers_of act
-
end
-
-
1
def notable_change?
-
390
!silent_change? && current_act_card? &&
-
15
(Card::Auth.current_id != WagnBotID) && followable?
-
end
-
-
1
def silent_change?
-
421
silent_change
-
end
-
-
1
private
-
-
1
def notify_followers_of act
-
11
act_followers(act).each_follower_with_reason do |follower, reason|
-
next if !follower.account || (follower == act.actor)
-
-
notify_follower follower, act, reason
-
end
-
end
-
-
1
def notify_follower follower, act, reason
-
follower.account.send_change_notice act, reason[:set_card].name, reason[:option]
-
end
-
-
1
def act_followers act
-
11
@follower_stash ||= FollowerStash.new
-
11
act.actions(false).each do |a|
-
31
next if !a.card || a.card.silent_change?
-
-
31
@follower_stash.check_card a.card
-
end
-
11
@follower_stash
-
end
-
-
1
def silent_change
-
@silent_change || @supercard&.silent_change
-
end
-
-
1
def current_act_card?
-
55
return false unless act_card
-
-
55
act_card.id.nil? || act_card.id == id
-
# FIXME: currently card_id is nil for deleted acts (at least
-
# in the store phase when it's tested). The nil test was needed
-
# to make this work.
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/notify.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Notify;
-
# Set: All cards (Notify, BaseViews)
-
#
-
1
module BaseViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/notify/base_views.rb"; end
-
2
module Format; module_parent.send :register_set_format, Card::Format, self; extend Card::Set::AbstractFormat
-
1
view :list_of_changes, denial: :blank, cache: :never do
-
4
action = notification_action voo.action_id
-
4
relevant_fields(action).map do |type|
-
8
edit_info_for(type, action)
-
end.compact.join
-
end
-
-
1
view :subedits, perms: :none, cache: :never do
-
4
return unless notification_act
-
-
4
wrap_subedits do
-
4
notification_act.actions_affecting(card).map do |action|
-
4
next if action.card_id == card.id
-
-
action.card.format(format: @format).render_subedit_notice action_id: action.id
-
end
-
end
-
end
-
-
1
view :subedit_notice, cache: :never do
-
action = notification_action voo.action_id
-
wrap_subedit_item do
-
%(#{name_before_action action} #{action.action_type}d\n) +
-
render_list_of_changes(action_id: action.id)
-
end
-
end
-
-
1
view :followed, perms: :none, compact: true do
-
4
if (set_card = followed_set_card) && (option_card = follow_option_card)
-
4
option_card.description set_card
-
else
-
"*followed set of cards*"
-
end
-
end
-
-
1
view :follower, perms: :none, compact: true do
-
active_notice(:follower) || "follower"
-
end
-
-
1
view :last_action_verb, cache: :never do
-
6
"#{notification_act&.main_action&.action_type || 'edite'}d"
-
end
-
-
1
view :unfollow_url, perms: :none, compact: true, cache: :never do
-
4
return "" unless (rule_name = live_follow_rule_name)
-
-
4
card_url path(mark: "#{active_notice(:follower)}+#{:follow.cardname}",
-
action: :update,
-
card: { subcards: { rule_name => Card[:never].name } })
-
end
-
-
1
def relevant_fields action
-
4
case action.action_type
-
4
when :create then %i[cardtype content]
-
when :update then %i[name cardtype content]
-
when :delete then %i[content]
-
end
-
end
-
-
1
def name_before_action action
-
(action.value(:name) && action.previous_value(:name)) || card.name
-
end
-
-
1
def followed_set_card
-
8
(set_name = active_notice(:followed_set)) && Card.fetch(set_name)
-
end
-
-
1
def follow_option_card
-
4
return unless (option_name = active_notice(:follow_option))
-
-
4
Card.fetch option_name
-
end
-
-
1
def active_notice key
-
20
@active_notice ||= inherit :active_notice
-
20
return unless @active_notice
-
-
20
@active_notice[key]
-
end
-
-
1
def live_follow_rule_name
-
4
return unless (set_card = followed_set_card) && (follower = active_notice(:follower))
-
-
4
set_card.follow_rule_name follower
-
end
-
-
1
def edit_info_for field, action
-
8
return nil unless (value = action.value field)
-
8
value = action.previous_value if action.action_type == :delete
-
8
wrap_list_item " #{notification_action_label action} #{field}: #{value}"
-
end
-
-
1
def notification_action_label action
-
8
case action.action_type
-
when :update then "new"
-
when :delete then "deleted"
-
end
-
end
-
-
1
def wrap_subedits
-
4
subedits = yield.compact.join
-
4
return "" if subedits.blank?
-
-
"\nThis update included the following changes:\n#{wrap_list subedits}"
-
end
-
-
1
def wrap_list list
-
"\n#{list}\n"
-
end
-
-
1
def wrap_list_item item
-
4
"#{item}\n"
-
end
-
-
1
def wrap_subedit_item
-
"\n#{yield}\n"
-
end
-
-
1
def notification_act act=nil
-
14
@notification_act ||= act || card.acts.last
-
end
-
-
1
def notification_action action_id
-
4
action_id ? Action.fetch(action_id) : card.last_action
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/notify/base_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module Notify;
-
# Set: All cards (Notify, HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/notify/html_views.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# view :last_action, perms: :none, cache: :never do
-
# _render_last_action_verb
-
# end
-
-
1
def wrap_list list
-
"<ul>#{list}</ul>\n"
-
end
-
-
1
def wrap_list_item item
-
4
"<li>#{item}</li>\n"
-
end
-
-
1
def wrap_subedit_item
-
"<li>#{yield}</li>\n"
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/all/notify/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Account" cards
-
#
-
1
module Account;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/account.rb"; end
-
1
def send_change_notice act, followed_set, follow_option
-
return unless email.present? && changes_visible?(act)
-
-
notify_of_act act do
-
{ follower: left.name, followed_set: followed_set, follow_option: follow_option }
-
end
-
end
-
-
1
def notify_of_act act
-
Auth.as(left.id) do
-
Card[:follower_notification_email].deliver(
-
act.card, { to: email }, auth: left, active_notice: yield
-
)
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/account.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Follow" cards
-
#
-
# The Right::Follow set configures follow preferences (`[Set]+[User]+:follow`)
-
# While the user follow dashboard ([User]+:follow`) is also in this Set, its
-
1
module Follow;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/follow.rb"; end
-
# customizations are handled in TypePlusRight::User::Follow
-
-
1
event :cache_expired_for_new_preference, :integrate, when: :is_preference? do
-
Card.follow_caches_expired
-
end
-
-
1
def option_cards
-
Card::FollowOption.cards.compact
-
end
-
-
1
def options_rule_card
-
Card.new(
-
name: "follow_options_card",
-
type_code: :pointer,
-
content: option_cards.map { |oc| "[[#{oc.name}]]" }.join("\n")
-
)
-
end
-
-
1
def add_follow_item? condition
-
new_card? || !include_item?(condition)
-
end
-
-
1
def ok_to_update
-
permit :update
-
end
-
-
1
def ok_to_create
-
permit :create
-
end
-
-
1
def ok_to_delete
-
permit :delete
-
end
-
-
1
def permit action, verb=nil
-
if %i[create delete update].include?(action) && allowed_to_change_follow_status?
-
true
-
else
-
super action, verb
-
end
-
end
-
-
1
def allowed_to_change_follow_status?
-
Auth.signed_in? &&
-
((user = rule_user) && Auth.current_id == user.id) || Auth.always_ok?
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# shows a follow item link for each of the current follow options
-
1
view :follow_status, cache: :never do
-
wrap { haml :follow_status }
-
end
-
-
# interface to view/alter a specific rule option
-
1
view :follow_item, cache: :never do
-
follow_item Env.params[:condition]
-
end
-
-
1
def follow_item condition, button=true
-
condition ||= "*always"
-
wrap do
-
card_form action: :update, success: { view: :follow_item } do
-
[
-
follow_item_hidden_tags(condition),
-
(follow_item_button(condition) if button),
-
follow_item_link(condition)
-
].compact
-
end
-
end
-
end
-
-
1
def rule_form_args
-
super.merge "data-update-foreign-slot": ".card-slot.follow_section-view"
-
end
-
-
1
private
-
-
1
def follow_item_hidden_tags condition
-
condkey = card.add_follow_item?(condition) ? :add_item : :drop_item
-
hidden_tags condition: condition, condkey => condition
-
end
-
-
1
def follow_item_button condition
-
action = card.add_follow_item?(condition) ? :add : :delete
-
button_tag type: :submit, "aria-label": "Left Align",
-
class: "btn-sm btn-item #{follow_item_button_class action}" do
-
follow_item_icon action
-
end
-
end
-
-
1
def follow_item_button_class action
-
action == :add ? "btn-item-add" : "btn-item-delete btn-primary"
-
end
-
-
1
def follow_item_icon action
-
icon_tag(action == :add ? :add : :check)
-
end
-
-
1
def follow_item_link condition
-
link_to_card follow_item_link_target, follow_item_link_text(condition)
-
end
-
-
1
def follow_item_link_target
-
set = card.rule_set
-
setname = set.name
-
set.tag.codename == :self ? setname.left : setname.field("by name")
-
end
-
-
1
def follow_item_link_text condition
-
if (option_card = Card.fetch condition)
-
option_card.description card.rule_set
-
else
-
card.rule_set.follow_label
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/follow.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+FollowFields" cards
-
#
-
1
module FollowFields;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/follow_fields.rb"; end
-
1
event :follow_fields_changed, :integrate do
-
Card.follow_caches_expired
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/follow_fields.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Followers" cards
-
#
-
# -*- encoding : utf-8 -*-
-
-
1
module Followers;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/followers.rb"; end
-
# X+*followers provides a list of all users following X.
-
-
1
include_set Abstract::Pointer
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core, cache: :never do
-
super()
-
end
-
end
-
-
1
def content
-
left ? item_names.to_pointer_content : ""
-
end
-
-
1
def item_names _args={}
-
left ? left.follow_set_card.prototype.follower_names : []
-
end
-
-
1
def virtual?
-
new?
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/followers.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Following" cards
-
#
-
1
module Following;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/following.rb"; end
-
1
def virtual?
-
new?
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
if card.left && Auth.signed_in?
-
render_rule_editor
-
else
-
nest Card.fetch(card.name.left, :followers), view: :titled, items: { view: :link }
-
end
-
end
-
-
1
view :status do
-
if (rcard = current_follow_rule_card)
-
rcard.item_cards.map do |item|
-
%(<div class="alert alert-success" role="alert">
-
<strong>#{rcard.rule_set.follow_label}</strong>: #{item.title}
-
</div>)
-
end.join
-
else
-
"No following preference"
-
end
-
end
-
-
1
view :one_line_content do
-
""
-
end
-
-
1
view :rule_editor, cache: :never do
-
rule_context = Card.fetch preference_name, new: { type_id: PointerID }
-
wrap_with :div, class: "edit-rule" do
-
follow_context = current_follow_rule_card || rule_context
-
subformat(follow_context).rule_form :open, rule_context, :modal
-
end
-
end
-
-
1
def preference_name
-
set_name = card.left.follow_set_card.name
-
Card::Name[set_name, Auth.current.name, :follow]
-
end
-
-
1
def edit_rule_success
-
{ view: "status", id: card.name.url_key }
-
end
-
-
1
def current_follow_rule_card
-
card.left.preference :follow
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/right/following.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Always"
-
#
-
1
module Always;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/always.rb"; end
-
1
include_set Abstract::FollowOption
-
-
1
follow_opts position: 2
-
-
1
follow_test { |_follower_id, _accounted_ids| true }
-
-
1
def title
-
"Following"
-
end
-
-
1
def label
-
"follow"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/always.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Created"
-
#
-
1
module Created;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/created.rb"; end
-
1
include_set Abstract::FollowOption
-
-
1
restrictive_follow_opts position: 1
-
-
1
follower_candidate_ids do |card|
-
62
[card.creator_id]
-
end
-
-
1
def title
-
"Following content you created"
-
end
-
-
1
def label
-
"follow if I created"
-
end
-
-
1
def description set_card
-
"#{set_card.follow_label} I created"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/created.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Edited"
-
#
-
1
module Edited;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/edited.rb"; end
-
1
include_set Abstract::FollowOption
-
-
1
restrictive_follow_opts position: 2
-
-
1
follower_candidate_ids do |card|
-
# FIXME? - could optimize by not using cards table...
-
62
card.id ? Card.search(editor_of: card.id, return: :id) : []
-
end
-
-
1
def title
-
"Following content you edited"
-
end
-
-
1
def label
-
"follow if I edited"
-
end
-
-
1
def description set_card
-
"#{set_card.follow_label} I edited"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/edited.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Follow"
-
#
-
1
module Follow;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/follow.rb"; end
-
1
extend Card::Setting
-
1
setting_opts group: :other, position: 7, rule_type_editable: false, user_specific: true
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/follow.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "FollowDefaults"
-
#
-
# DEPRECATED
-
#
-
# Despite its name (*follow defaults)card does not influence defaults for *follow rules.
-
# What it does is provide a mechanism (with interface) for updating all users so that
-
# they follow the items that are its content.
-
#
-
# PLAN:
-
1
module FollowDefaults;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/follow_defaults.rb"; end
-
# - actual defaults should be handled as much as possible with something like
-
# the *defaults rule
-
# - on the *admin page, we can have a link so sharks can update all the pristine cards
-
# to use whatever the actual defaults representation is (see previous point)
-
# - if you truly want to override existing follow rules, that may be monkey territory?
-
# - we will delete "*follow defaults" after the above are completed
-
-
1
event :update_follow_rules, :finalize, on: :save, when: :update_all_users do
-
Auth.as_bot do
-
Card.search(type: "user").each do |user|
-
follow_defaults.each do |set_card, option|
-
follow_rule = Card.fetch(set_card.follow_rule_name(user.name), new: {})
-
next unless follow_rule
-
-
follow_rule.drop_item "*never"
-
follow_rule.drop_item "*always"
-
follow_rule.add_item option
-
follow_rule.save!
-
end
-
end
-
end
-
Card.follow_caches_expired
-
end
-
-
1
def follow_defaults
-
item_names.map do |item|
-
if (set_card = Card.fetch item.to_name.left)&.type_code == :set
-
[set_card, follow_option(item)]
-
end
-
end.compact
-
end
-
-
1
def follow_option item
-
option_card =
-
Card.fetch(item.to_name.right) || Card[item.to_name.right.to_sym]
-
option_card.follow_option? ? option_card.name : "*always"
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :edit, perms: :update, unknown: true do
-
frame_and_form :update, hidden: { success: "_self",
-
card: { update_all_users: false } } do
-
[
-
_render_content_formgroups,
-
_render_confirm_update_all,
-
_render_edit_buttons
-
]
-
end
-
end
-
-
1
view :edit_buttons do
-
button_formgroup do
-
[submit_and_update_button, simple_submit_button, cancel_to_edit_button]
-
end
-
end
-
-
1
def submit_and_update_button
-
submit_button text: "Submit and update all users",
-
disable_with: "Updating", class: "follow-updater"
-
end
-
-
1
def simple_submit_button
-
button_tag "Submit", class: "follow"
-
end
-
-
1
def cancel_to_edit_button
-
cancel_button href: path(view: :edit, id: card.id)
-
end
-
-
1
view :confirm_update_all do
-
wrap do
-
alert "info" do
-
%(
-
<h1>Are you sure you want to change the default follow rules?</h1>
-
<p>You may choose to update all existing users.
-
This may take a while. </p>
-
)
-
end
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/follow_defaults.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "Never"
-
#
-
1
module Never;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/never.rb"; end
-
1
include_set Abstract::FollowOption
-
-
1
follow_opts position: 3
-
-
1
follow_test { |_follower_id, _accounted_ids| false }
-
-
1
def title
-
"Ignoring"
-
end
-
-
1
def label
-
"ignore"
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/self/never.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Cardtype" cards
-
#
-
1
module Cardtype;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/type/cardtype.rb"; end
-
1
def follow_label
-
follow_set_card.follow_label
-
end
-
-
1
def followed_by? user_id=nil
-
follow_set_card.all_members_followed_by? user_id
-
end
-
-
1
def follow_set_card
-
Card.fetch name, :type
-
end
-
-
1
def list_direct_followers?
-
true
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def related_by_type_items
-
super.unshift ["#{card.name} cards", [card, :type, :by_name], mark: :absolute]
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/type/cardtype.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Set" cards
-
#
-
1
module Set;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/type/set.rb"; end
-
1
event :cache_expired_for_new_set, :store, on: :create do
-
9
Card.follow_caches_expired
-
end
-
-
1
def list_direct_followers?
-
true
-
end
-
-
1
def follow_label
-
4
if (klass = subclass_for_set)
-
4
klass.short_label name.left_name
-
else
-
""
-
end
-
end
-
-
1
def follow_rule_name user=nil
-
4
Card::Name[[name, user, :follow].compact]
-
end
-
-
1
def followed_by? user_id=nil
-
all_members_followed_by? user_id
-
end
-
-
1
def follow_set_card
-
self
-
end
-
-
1
def all_members_followed?
-
all_members_followed_by? Auth.current_id
-
end
-
-
1
def all_members_followed_by? user_id=nil
-
return false unless prototype.followed_by?(user_id)
-
-
directly_followed_by?(user_id) || broader_set_followed_by?(user_id)
-
end
-
-
1
def broader_set_followed_by? user_id
-
broader_sets.find do |set_name|
-
Card.fetch(set_name)&.directly_followed_by? user_id
-
end
-
end
-
-
1
def directly_followed?
-
directly_followed_by? Auth.current_id
-
end
-
-
1
def directly_followed_by? user_id=nil
-
return true if user_id && follow_rule?(user_id)
-
-
follow_rule?
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/type/set.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "User" cards
-
#
-
1
module User;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/type/user.rb"; end
-
1
def follow follow_name, option="*always"
-
return unless (follow_rule = Card.fetch(follow_name)&.follow_rule_card(name, new: {}))
-
-
follow_rule.drop_item "*never"
-
follow_rule.add_item option
-
follow_rule.save!
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/type/user.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class TypePlusRight; module User;
-
# Set: All "+Follow" cards on "User" cards
-
#
-
1
module Follow;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/type_plus_right/user/follow.rb"; end
-
1
FOLLOW_TABS = { "Follow" => "follow_tab", "Ignore" => "ignore_tab" }.freeze
-
-
# a virtual pointer to the sets that a user is following.
-
# (data is stored in preferences: `[Set]+[User]+:follow`)
-
-
1
include_set Abstract::Pointer
-
1
def virtual?
-
new?
-
end
-
-
# overrides pointer default
-
1
def item_names _args={}
-
if (user = left)
-
Card::Rule.preference_names user.name, "follow"
-
else
-
[]
-
end
-
end
-
-
1
def suggestions
-
Card[:follow_suggestions]&.item_names || []
-
end
-
-
1
def current_user?
-
Auth.signed_in? && Auth.current_id == left.id
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :one_line_content do
-
""
-
end
-
-
1
view :edit do
-
render :open
-
end
-
-
# renders follow tab and ignore tab
-
1
view :core do
-
tabs FOLLOW_TABS, "follow_tab", load: :lazy do
-
render_follow_tab
-
end
-
end
-
-
1
view :follow_tab, cache: :never do
-
haml :follow_editor, items_method: :following_rules_and_options
-
end
-
-
1
view :ignore_tab, cache: :never do
-
haml :follow_editor, items_method: :ignoring_rules_and_options
-
end
-
-
1
def show_button?
-
card.current_user? || Auth.always_ok?
-
end
-
-
1
def pointer_items args
-
voo.items[:view] ||= :link
-
super(args)
-
end
-
-
# TODO: research and generalize
-
# this does not look specific to following!
-
1
view :errors, perms: :none do
-
return unless card.errors.any?
-
-
if card.errors.find { |attrib, _msg| attrib == :permission_denied }
-
Env.save_interrupted_action(request.env["REQUEST_URI"])
-
voo.title = "Problems with #{card.name}"
-
class_up "d0-card-frame", "card card-warning card-inverse"
-
frame do
-
"Please #{link_to_card :signin, 'sign in'}" # " #{to_task}"
-
end
-
else
-
super()
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/type_plus_right/user/follow.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class TypePlusRight; module User;; module Follow;
-
# Set: All "+FollowEditorHelper" cards on "User+Follow" cards (FollowEditorHelper)
-
#
-
# all the following methods are used to construct the Follow and Ignore tabs
-
-
1
module FollowEditorHelper;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-follow/set/type_plus_right/user/follow/follow_editor_helper.rb"; end
-
# TODO: these object representations are complex enough for their own class
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# constructs hash of rules/options for "Follow" tab
-
1
def following_rules_and_options &block
-
rule_opt_array = following_rule_options_hash.map do |key, val|
-
[(Card.fetch key, new: {}), val]
-
end
-
rules_and_options_by_set_pattern Hash[rule_opt_array], &block
-
end
-
-
# constructs hash of rules/options for "Ignore" tab
-
1
def ignoring_rules_and_options &block
-
rule_opts_hash = ignore_rules.each_with_object({}) do |rule, hash|
-
hash[rule] = [:never.cardname]
-
end
-
rules_and_options_by_set_pattern rule_opts_hash, &block
-
end
-
-
1
private
-
-
# all rules with ignore
-
1
def ignore_rules
-
never = :never.cardname.key
-
card.item_cards.select do |follow_rule|
-
follow_rule.item_names.select { |n| n.key == never }.any?
-
end
-
end
-
-
# @param rule_opts_hash [Hash] { rule1_card => rule1_follow_options }
-
# for each rule/option variant, yields with rule_card and option params
-
1
def rules_and_options_by_set_pattern rule_opts_hash
-
pattern_hash = a_set_pattern_hash rule_opts_hash
-
empty = true
-
Card.set_patterns.reverse.map do |pattern|
-
pattern_hash[pattern].each do |rule_card, options|
-
options.each do |option|
-
yield rule_card, option
-
empty = false
-
end
-
end
-
end
-
yield nil if empty
-
end
-
-
1
def a_set_pattern_hash rule_opts_hash
-
pattern_hash = Hash.new { |h, k| h[k] = [] }
-
rule_opts_hash.each do |rule_card, options|
-
pattern_hash[rule_card.rule_set.subclass_for_set] << [rule_card, options]
-
end
-
pattern_hash
-
end
-
-
# @return Hash # { rule1 => rule1_follow_options }
-
1
def following_rule_options_hash
-
merge_option_hashes current_following_rule_options_hash,
-
suggested_following_rule_options_hash
-
end
-
-
# adds suggested follow options to existing rules where applicable
-
1
def merge_option_hashes current, suggested
-
current.each do |key, current_opt|
-
if (suggested_opt = suggested.delete(key))
-
current[key] = (current_opt + suggested_opt).uniq
-
end
-
end
-
current.merge suggested
-
end
-
-
# @return Hash # { existing_rule1 => rule1_follow_options } (excluding never)
-
# (*never is excluded because this list is for the Follow tab, and *never is
-
# handled under the Ignore tab)
-
1
def current_following_rule_options_hash
-
never = :never.cardname
-
card.item_cards.each_with_object({}) do |follow_rule, hash|
-
hash[follow_rule.key] = follow_rule.item_names.reject { |item| item == never }
-
end
-
end
-
-
# @return Hash # { suggested_rule1 => rule1_follow_options }
-
1
def suggested_following_rule_options_hash
-
return {} unless card.current_user?
-
-
card.suggestions.each_with_object({}) do |sug, hash|
-
set_card, opt = a_set_and_option_suggestion(sug) || a_set_only_suggestion(sug)
-
hash[set_card.follow_rule_name(card.trunk).key] = [opt]
-
end
-
end
-
-
# @param sug [String] follow suggestion
-
# @return [Array] set_card and option
-
# suggestion value contains both set and follow option
-
1
def a_set_and_option_suggestion sug
-
return unless (set_card = valid_set_card(sug.to_name.left))
-
-
[set_card, suggested_follow_option(sug.to_name.right)]
-
end
-
-
1
def suggested_follow_option name
-
# FIXME: option should be unambiguously name or codename
-
# (if codename use colon or Symbol)
-
option_card = Card.fetch(name) || Card[name.to_sym]
-
option_card&.follow_option? ? option_card.name : :always.cardname
-
end
-
-
# @param sug [String] follow suggestion
-
# @return [Array] set_card and option
-
# suggestion value contains only set (implies *always)
-
1
def a_set_only_suggestion sug
-
return unless (set_card = valid_set_card(sug))
-
-
yield set_card, :always.cardname
-
end
-
-
1
def valid_set_card name
-
card = Card.fetch(name)
-
card&.type_code == :set ? card : false
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-follow/set/type_plus_right/user/follow/follow_editor_helper.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (GoogleAnalytics)
-
#
-
1
module GoogleAnalytics;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-google_analytics/set/all/google_analytics.rb"; end
-
1
require "staccato"
-
-
1
mattr_accessor :server_side_tracking_formats
-
-
1
self.server_side_tracking_formats = %i[csv json]
-
-
1
event :track_page, before: :show_page, when: :track_page? do
-
tracker.pageview path: Env.controller.request&.path, host: Env.host, title: name
-
end
-
-
1
def track_page?
-
31
google_analytics_key &&
-
Env.controller&.response_format&.in?(server_side_tracking_formats)
-
end
-
-
1
def tracker
-
return unless google_analytics_key
-
-
::Staccato.tracker google_analytics_key # , nil, ssl: true
-
end
-
-
1
def google_analytics_key
-
54
@google_analytics_key ||=
-
Card::Rule.global_setting(:google_analytics_key) ||
-
Card.config.google_analytics_key
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
delegate :tracker, :google_analytics_key, to: :card
-
-
1
def views_in_head
-
23
super << :google_analytics_snippet
-
end
-
-
1
view :google_analytics_snippet, unknown: true, perms: :none do
-
23
haml :google_analytics_snippet if google_analytics_key
-
end
-
-
1
def google_analytics_snippet_vars
-
{ anonymizeIp: true }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-google_analytics/set/all/google_analytics.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Markdown" cards
-
#
-
1
module Markdown;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-markdown/set/type/markdown.rb"; end
-
1
require "kramdown"
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
10
safe_process_content do |content|
-
10
Kramdown::Document.new(content).to_html
-
end
-
end
-
-
1
def input_type
-
:ace_editor
-
end
-
-
1
def ace_mode
-
:markdown
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-markdown/set/type/markdown.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (ProsemirrorEditor)
-
#
-
1
module ProsemirrorEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/all/prosemirror_editor.rb"; end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def prosemirror_editor_input
-
wrap_with :div, id: unique_id, class: "prosemirror-editor" do
-
hidden_field :content, class: "d0-card-content", value: card.content
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/all/prosemirror_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptProsemirror"
-
#
-
1
module ScriptProsemirror;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/self/script_prosemirror.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptMods.add_item :script_prosemirror
-
1
Self::InputOptions.add_to_basket :options, "prosemirror editor"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/self/script_prosemirror.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptProsemirrorConfig"
-
#
-
1
module ScriptProsemirrorConfig;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/self/script_prosemirror_config.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptEditors.add_item :script_prosemirror_config
-
1
All::Head::HtmlFormat.add_to_basket :mod_js_config,
-
[:prose_mirror, "setProseMirrorConfig"]
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/self/script_prosemirror_config.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "StyleProsemirror"
-
#
-
1
module StyleProsemirror;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/self/style_prosemirror.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::StyleMods.add_item :style_prosemirror
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-prosemirror_editor/set/self/style_prosemirror.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (Recaptcha)
-
#
-
1
module Recaptcha;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/all/recaptcha.rb"; end
-
RECAPTCHA_ERROR_CODES = { # LOCALIZE
-
1
"missing-input-secret" => "secret parameter is missing",
-
"invalid-input-secret" => "secret parameter is invalid or malformed",
-
"missing-input-response" => "response parameter is missing",
-
"invalid-input-response" => "response parameter is invalid or malformed",
-
"bad-request" => "request is invalid or malformed"
-
}
-
-
1
def human?
-
result = JSON.parse recaptcha_response
-
return if recaptcha_success?(result)
-
-
add_recaptcha_errors result["error-codes"]
-
end
-
-
1
def recaptcha_on?
-
185
recaptcha_keys? &&
-
Env[:controller] &&
-
!Auth.signed_in? &&
-
!Auth.always_ok? &&
-
!Auth.needs_setup? &&
-
Card::Rule.toggle(rule(:captcha))
-
end
-
-
1
def add_recaptcha_errors error_codes
-
if error_codes.present?
-
error_codes.each do |code|
-
errors.add :recaptcha, RECAPTCHA_ERROR_CODES.fetch(code, code)
-
end
-
else
-
errors.add :recaptcha, "Looks like you are not a human" # LOCALIZE
-
end
-
end
-
-
1
def recaptcha_success? result
-
result['success'] &&
-
(result['score'].to_f >= Cardio.config.recaptcha_minimum_score) &&
-
(result['action'].to_sym == action.to_sym)
-
end
-
-
1
def recaptcha_response
-
::Recaptcha.get({ secret: Card.config.recaptcha_secret_key,
-
response: Env.params[:recaptcha_token] }, {})
-
end
-
-
1
def recaptcha_keys?
-
185
Card.config.recaptcha_site_key && Card.config.recaptcha_secret_key
-
end
-
-
1
event :recaptcha, :validate, when: :validate_recaptcha? do
-
handle_recaptcha_config_errors do
-
Env[:recaptcha_used] = true
-
human?
-
end
-
end
-
-
1
def handle_recaptcha_config_errors
-
if Env.params[:recaptcha_token] == "grecaptcha-undefined"
-
errors.add "recaptcha", "needs correct v3 configuration" # LOCALILZE
-
elsif Env.params[:recaptcha_token] == "recaptcha-token-field-missing"
-
raise Card::Error, "recaptcha token field missing" # LOCALILZE
-
else
-
yield
-
end
-
end
-
-
-
1
def validate_recaptcha?
-
332
!@supercard && !Env[:recaptcha_used] && recaptcha_on?
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def recaptcha_token action
-
1
output [
-
javascript_include_tag(recaptcha_script_url),
-
hidden_field_tag("recaptcha_token", "",
-
"data-site-key": Card.config.recaptcha_site_key,
-
"data-action": action,
-
class: "_recaptcha-token")
-
]
-
end
-
-
1
def recaptcha_script_url
-
1
"https://www.google.com/recaptcha/api.js?render=#{Card.config.recaptcha_site_key}"
-
end
-
-
1
def hidden_form_tags action, opts
-
20
return super unless recaptcha?(opts)
-
-
1
super + recaptcha_token(action)
-
end
-
-
1
def card_form_html_opts action, opts={}
-
20
super
-
20
opts["data-recaptcha"] ||= "on" if recaptcha?(opts)
-
20
opts
-
end
-
-
1
def recaptcha? opts
-
40
card.recaptcha_on? && opts[:recaptcha] != :off
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/all/recaptcha.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "AdminInfo"
-
#
-
1
module AdminInfo;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/admin_info.rb"; end
-
1
add_to_basket :warnings, :recaptcha_config_issues
-
-
1
def recaptcha_config_issues?
-
RecaptchaCard.using_defaults?
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def recaptcha_config_issues_message
-
warning =
-
if Card::Env.localhost?
-
# %(Your captcha is currently working with temporary settings.
-
# This is fine for a local installation, but you will need new
-
# recaptcha keys if you want to make this site public.)
-
I18n.t(:captcha_temp, scope: "mod.admin.set.self.admin_info",
-
recaptcha_link: add_recaptcha_keys_link)
-
else
-
# %(You are configured to use [[*captcha]], but for that to work
-
# you need new recaptcha keys.)
-
I18n.t(:captcha_keys, scope: "mod.admin.set.self.admin_info",
-
recaptcha_link: add_recaptcha_keys_link,
-
captcha_link: link_to_card(:captcha))
-
end
-
<<-HTML
-
<p>#{warning}</p>
-
HTML
-
end
-
-
1
def add_recaptcha_keys_link
-
link_text = I18n.t :recaptcha_keys, scope: "mod.admin.set.self.admin_info"
-
Card[:recaptcha_settings]&.format&.edit_link link_text: link_text
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/admin_info.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "RecaptchaProxy"
-
#
-
1
module RecaptchaProxy;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_proxy.rb"; end
-
1
event :set_recaptcha_proxy, :finalize do
-
Card.config.recaptcha_proxy = content
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_proxy.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "RecaptchaSecretKey"
-
#
-
1
module RecaptchaSecretKey;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_secret_key.rb"; end
-
1
event :validate_recaptcha_secret_key, :validate do
-
return if content.match?(/^[a-zA-Z0-9\-_]*$/)
-
-
errors.add :content, "invalid key" # LOCALIZE
-
end
-
-
1
event :set_recaptcha_secret_key, :finalize do
-
Card.config.recaptcha_secret_key = content
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_secret_key.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "RecaptchaSettings"
-
#
-
1
module RecaptchaSettings;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_settings.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def raw_help_text
-
# LOCALIZE
-
"Register your domain at Google's [[http://google.com/recaptcha|reCAPTCHA service]] "\
-
"and enter your site key and secret key below.<br>"\
-
"If you want to turn catchas off then change all [[*captcha|captcha rules]] to 'no'."
-
end
-
-
# def instructions title, steps
-
# steps = list_tag steps, ordered: true
-
# "#{title}#{steps}"
-
# end
-
#
-
# <h5>#{instructions}</h5>
-
# #{howto_add_new_recaptcha_keys}
-
# #{howto_turn_captcha_off}
-
#
-
# def howto_add_new_recaptcha_keys
-
# instructions(
-
# I18n.t(:howto_add_keys, scope: "mod.admin.set.self.admin_info"),
-
# [
-
# I18n.t(:howto_register,
-
# scope: "mod.admin.set.self.admin_info",
-
# recaptcha_link: link_to_resource("http://google.com/recaptcha")),
-
# I18n.t(:howto_add,
-
# scope: "mod.admin.set.self.admin_info",
-
# recaptcha_settings: link_to_card(:recaptcha_settings))
-
# ]
-
# )
-
# end
-
#
-
# def howto_turn_captcha_off
-
# instructions(
-
# I18n.t(:howto_turn_off, scope: "mod.admin.set.self.admin_info"),
-
# [
-
# I18n.t(:howto_go,
-
# scope: "mod.admin.set.self.admin_info",
-
# captcha_card: link_to_card(:captcha)),
-
# I18n.t(:howto_update,
-
# scope: "mod.admin.set.self.admin_info")
-
# ]
-
# )
-
# end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_settings.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "RecaptchaSiteKey"
-
#
-
1
module RecaptchaSiteKey;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_site_key.rb"; end
-
1
event :validate_recaptcha_site_key, :validate do
-
return if content.match?(/^[a-zA-Z0-9\-_]*$/)
-
-
errors.add :content, "invalid key" # LOCALIZE
-
end
-
-
1
event :set_recaptcha_site_key, :finalize do
-
Card.config.recaptcha_site_key = content
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-recaptcha/set/self/recaptcha_site_key.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Self" cards
-
#
-
1
module Self;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/right/self.rb"; end
-
1
def prototype_default_card
-
left
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/right/self.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rstar
-
# Set: All "+*" cards (RuleUser)
-
#
-
1
module RuleUser;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rstar/rule_user.rb"; end
-
-
1
def rule_user_name
-
is_preference? ? name.trunk_name.tag : nil
-
end
-
-
1
def rule_user
-
is_preference? ? self[-2] : nil
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rstar/rule_user.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (BarView)
-
#
-
1
module BarView;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/bar_view.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
bar_cols 6, 6
-
1
info_bar_cols 5, 4, 3
-
-
1
def existing_rule_card
-
@existing_rule_card ||= find_existing_rule_card
-
end
-
-
1
view :bar, unknown: true do
-
voo.hide :bar_nav unless existing_rule_card
-
super()
-
end
-
-
1
view :expanded_bar, unknown: true do
-
super()
-
end
-
-
1
view :one_line_content,
-
wrap: { div: { class: "text-muted one-line" } }, unknown: true do
-
return render_mini_unknown unless existing_rule_card
-
-
with_nest_mode :compact do
-
one_line_content
-
end
-
end
-
-
1
view :raw_one_line_content,
-
wrap: { div: { class: "text-muted one-line" } }, unknown: true do
-
return render_mini_unknown unless existing_rule_card
-
-
raw_one_line_content
-
end
-
-
1
view :bar_bottom, unknown: true do
-
if nest_mode == :edit
-
current_rule_form
-
else
-
nest existing_rule_card, view: :core
-
end
-
end
-
-
1
view :bar_middle, unknown: true do
-
rule_info
-
end
-
-
1
view :bar_left, unknown: true do
-
super()
-
end
-
-
1
view :bar_right, unknown: true do
-
voo.show?(:bar_bottom) ? rule_info : rule_short_content
-
end
-
-
1
def rule_short_content
-
return "" unless existing_rule_card
-
-
nest existing_rule_card, { view: :one_line_content },
-
set_context: card.name.trunk_name
-
end
-
-
1
def bar_title
-
return super() if voo.show? :full_name
-
-
linking_to_existing_rule { card.rule_setting_title }
-
end
-
-
# LOCALIZE
-
1
def rule_info
-
return wrap_with(:em, "no existing #{setting_link} rule") unless existing_rule_card
-
-
wrap_with :span,
-
"#{rule_setting_link} rule that applies to "\
-
"#{rule_set_link existing_rule_card}"
-
end
-
-
1
def rule_setting_link
-
link_to_card card.rule_setting, card.rule_setting_name
-
end
-
-
1
def rule_set_link existing_rule
-
count = link_to_card [card.rule_set, :by_name], card.rule_set.count
-
"#{link_to_card card.rule_set, existing_rule.trunk&.label&.downcase} (#{count})"
-
end
-
-
1
private
-
-
1
def linking_to_existing_rule
-
return yield unless existing_rule_card && voo.show?(:toggle)
-
-
link_to_view bar_title_toggle_view, yield
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/bar_view.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (BridgeRulesEditor)
-
#
-
1
module BridgeRulesEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/bridge_rules_editor.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :overlay_rule, cache: :never, unknown: true do
-
wrap_with_overlay slot: breadcrumb_data("Rule editing", "rules") do
-
current_rule_form
-
end
-
end
-
-
1
view :modal_rule, cache: :never, unknown: true,
-
wrap: { modal: { title: ->(format) { format.render_title } } } do
-
current_rule_form
-
end
-
-
1
view :overlay_title do
-
edit_rule_title
-
end
-
-
1
view :help_text, unknown: true, cache: :never do
-
wrap_help_text [rule_based_help, setting_link].join(" ")
-
end
-
-
1
def setting_link
-
wrap_with :div, class: "ml-auto" do
-
link_to_card card.rule_setting_name,
-
" (#{card.rule_setting.count} #{card.rule_setting_title} rules)",
-
class: "text-muted"
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/bridge_rules_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (Editor)
-
#
-
1
module Editor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/editor.rb"; end
-
1
def left_type_for_nest_editor_set_selection
-
return super unless is_template?
-
-
case Card.fetch_id rule_set_pattern_name
-
when TypeID
-
rule_set.anchor_name
-
when SelfID
-
rule_set.anchor.type_name
-
else
-
super
-
end
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
attr_accessor :rule_context
-
-
1
view :rule_edit, cache: :never, unknown: true,
-
wrap: { modal: { size: :large,
-
title: :edit_rule_title,
-
footer: "" } } do
-
current_rule_form form_type: :modal
-
end
-
-
1
view :rule_help, unknown: true, perms: :none, cache: :never do
-
wrap_with :div, class: "alert alert-info rule-instruction" do
-
rule_based_help
-
end
-
end
-
-
1
view :rule_bridge_link, unknown: true do
-
opts = bridge_link_opts(class: "edit-rule-link nav-link",
-
"data-toggle": "pill",
-
"data-cy": "#{setting_title.to_name.key}-pill")
-
opts[:path].delete(:layout)
-
link_to_view(:overlay_rule, (setting_title + short_help_text), opts)
-
end
-
-
1
def edit_link_view
-
:rule_edit
-
end
-
-
1
def edit_rule_title
-
output [
-
wrap_with(:h5, setting_title, class: "title font-weight-bold")
-
# render_overlay_rule_help
-
]
-
end
-
-
1
def current_rule
-
if params[:assign]
-
card
-
elsif (existing = find_existing_rule_card)
-
existing
-
else
-
card
-
end
-
end
-
-
1
def quick_editor
-
rule_content_formgroup
-
end
-
-
1
def setting_title
-
card.name.tag.tr "*", ""
-
end
-
-
1
def short_help_text
-
"<div class=\"help-text\">#{card.short_help_text}</div>"
-
end
-
-
1
def rule_set_description
-
card.rule_set.follow_label
-
end
-
-
1
def rules_type_formgroup
-
return unless card.right.rule_type_editable
-
-
success = @edit_rule_success
-
wrap_type_formgroup do
-
type_field(
-
href: path(mark: success[:id], view: :rule_form, assign: true),
-
class: "type-field rule-type-field live-type-field",
-
"data-remote" => true
-
)
-
end
-
end
-
-
1
def rule_content_formgroup
-
_render_content_formgroup hide: :conflict_tracker
-
end
-
-
1
def current_set_key
-
card.new_card? ? Card.quick_fetch(:all).name.key : card.rule_set_key
-
end
-
-
1
private
-
-
1
def find_existing_rule_card
-
card.new_card? ? existing_rule_from_prototype : card
-
end
-
-
# self.card is a POTENTIAL rule; it quacks like a rule but may or may not exist.
-
# This generates a prototypical member of the POTENTIAL rule's set
-
# and returns that member's ACTUAL rule for the POTENTIAL rule's setting
-
1
def existing_rule_from_prototype
-
return unless (setting = card.right)
-
-
card.set_prototype.rule_card setting.codename, user: card.rule_user
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/html_views.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
# Rule cards that are searches are usual right structures and refer to the left
-
# in the search query. In that case the search doesn't work
-
# properly in the context of the rule card itself. Hence we show the query syntax
-
# and not the search result.
-
10
if card.type_id == SearchTypeID
-
render_raw
-
else
-
10
super()
-
end
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (QuickEditor)
-
#
-
1
module QuickEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/quick_editor.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :quick_edit, unknown: true, wrap: :slot do
-
quick_edit
-
end
-
-
1
view :quick_edit_success do
-
set_info true
-
end
-
-
1
def quick_edit
-
haml :quick_edit
-
end
-
-
1
def quick_form
-
card_form :update, quick_form_opts do
-
quick_editor
-
end
-
end
-
-
1
def quick_form_opts
-
{ "data-slot-selector": ".set-info.card-slot",
-
success: { view: :quick_edit_success } }
-
end
-
-
1
def set_info notify_change=nil
-
wrap true, class: "set-info" do
-
haml :set_info, notify_change: notify_change
-
end
-
end
-
-
1
def undo_button
-
link_to "undo", method: :post, rel: "nofollow", remote: true,
-
class: "btn btn-secondary ml-2 btn-sm btn-reduced-padding slotter",
-
"data-slot-selector": ".card-slot.quick_edit-view",
-
path: { action: :update,
-
revert_actions: [card.last_action_id],
-
revert_to: :previous }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/quick_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (RuleForm)
-
#
-
1
module RuleForm;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :rule_form, cache: :never, unknown: true do
-
@success_view ||= :open
-
@rule_context ||= card
-
@form_type ||= :overlay
-
-
wrap do
-
edit_rule_form @success_view do
-
[
-
hidden_tags(success: @edit_rule_success),
-
haml(:rule_form)
-
].join
-
end
-
end
-
end
-
-
1
def form_type
-
@form_type || :overlay
-
end
-
-
1
def current_rule_form success_view: :overlay_rule, form_type: :overlay
-
current_rule_format = subformat current_rule
-
current_rule_format.rule_form success_view, card, form_type
-
end
-
-
1
def rule_form success_view, rule_context, form_type=:overlay
-
validate_form_type form_type
-
-
@rule_context = rule_context
-
@form_type = form_type
-
@success_view = success_view
-
-
render_rule_form
-
end
-
-
1
def validate_form_type form_type
-
return if form_type.in? %i[overlay modal]
-
-
raise "invalid rule_form type: #{form_type}; has to be overlay or modal"
-
end
-
-
1
def edit_rule_form success_view, &block
-
@rule_context ||= card
-
@edit_rule_success = edit_rule_success(success_view)
-
action_args = { action: :update, no_mark: true }
-
card_form action_args, rule_form_args, &block
-
end
-
-
1
def rule_form_args
-
{ class: "card-rule-form", "data-slotter-mode": "update-origin" }
-
end
-
-
1
def edit_rule_success view="overlay_rule"
-
{ id: @rule_context.name.url_key,
-
view: view }
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Rule; module RuleForm;
-
# Set: All rule cards (RuleForm, Buttons)
-
#
-
1
module Buttons;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/buttons.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def edit_rule_buttons
-
wrap_with(:div, class: "button-area") do
-
[
-
standard_save_button(class: "_rule-submit-button"),
-
standard_save_and_close_button(class: "_rule-submit-button", close: form_type),
-
edit_rule_cancel_button,
-
edit_rule_delete_button
-
]
-
end
-
end
-
-
1
def edit_rule_cancel_button
-
send "#{form_type}_close_button", "Cancel", situation: "secondary", class: "btn-sm"
-
end
-
-
1
def edit_rule_delete_button args={}
-
return if card.new_card?
-
-
delete_opts = {
-
confirm: delete_confirm(args[:fallback_set]),
-
# success: @edit_rule_success,
-
no_success: true,
-
"data-slotter-mode": "silent-success",
-
class: "_close-#{form_type}-on-success"
-
}
-
delete_opts["data-slot-selector"] = slot_selector if args[:slot_selector]
-
wrap_with :span, class: "rule-delete-section" do
-
delete_button delete_opts
-
end
-
end
-
-
1
def delete_confirm fallback_set
-
setting = card.rule_setting_name
-
-
if fallback_set && (fallback_set_card = Card.fetch(fallback_set))
-
"Deleting will revert to #{setting} rule for #{fallback_set_card.label}"
-
else
-
"Are you sure you want to delete the #{setting} rule for #{rule_set_description}?"
-
end
-
end
-
-
1
def edit_rule_submit_button
-
submit_button class: "_rule-submit-button"
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/buttons.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Rule; module RuleForm;
-
# Set: All rule cards (RuleForm, FormElements)
-
#
-
1
module FormElements;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/form_elements.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
#### DEPRECATED
-
-
1
def rule_set_selection
-
wrap_with :div, class: "set-list" do
-
[rule_set_formgroup, related_set_formgroup]
-
end
-
end
-
-
1
def rule_set_formgroup
-
tag = @rule_context.rule_user_setting_name
-
narrower = []
-
option_list "Set" do
-
rule_set_options.map do |set_name, state|
-
rule_set_radio_button set_name, tag, state, narrower
-
end
-
end
-
end
-
-
1
def related_set_formgroup
-
related_sets = related_sets_in_context
-
return "" unless related_sets&.present?
-
-
tag = @rule_context.rule_user_setting_name
-
option_list "related set" do
-
related_rule_radios related_sets, tag
-
end
-
end
-
-
1
def related_sets_in_context
-
set_context = @rule_context.rule_set_name
-
set_context && Card.fetch(set_context).prototype.related_sets
-
end
-
-
1
def option_list title
-
formgroup title, input: "set", class: "col-xs-6", help: false do
-
wrap_with :ul do
-
wrap_each_with(:li, class: "radio") { yield }
-
end
-
end
-
end
-
-
1
def related_rule_radios related_sets, tag
-
related_sets.map do |set_name, _label|
-
rule_name = "#{set_name}+#{tag}"
-
state = Card.exists?(rule_name) ? :exists : nil
-
rule_radio set_name, state do
-
radio_button :name, rule_name
-
end
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/form_elements.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (RuleForm)
-
#
-
#! no set module
-
1
module RuleForm;
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/rule_set_radio.rb"; end
-
1
class RuleSetRadio
-
1
attr_reader :format
-
1
delegate :link_to_card, :radio_button, :wrap_with, :icon_tag,
-
to: :format
-
-
# @param state [:current, :overwritten]
-
1
def initialize format, set_name, tag, state
-
@format = format
-
@card = format.card
-
@set_name = set_name
-
@tag = tag
-
@state = state
-
end
-
-
1
def html narrower
-
@narrower_rules = narrower
-
-
rule_radio do
-
radio_text = "#{@set_name}+#{@tag}"
-
radio_button :name, radio_text, checked: false, warning: warning
-
end
-
end
-
-
1
private
-
-
1
def current?
-
@state == :current
-
end
-
-
1
def overwritten?
-
@state == :overwritten
-
end
-
-
1
def rule_radio
-
label_classes = ["set-label", ("current-set-label" if current?)]
-
icon = icon_tag "open_in_new", "link-muted"
-
wrap_with :label, class: label_classes.compact.join(" ") do
-
[yield, label, link_to_card(@set_name, icon, target: "decko_set")]
-
end
-
end
-
-
1
def label
-
label = Card.fetch(@set_name).label
-
label += " <em>#{extra_info}</em>".html_safe if extra_info
-
label
-
end
-
-
1
def extra_info
-
case @state
-
when :current
-
"(current)"
-
when :overwritten, :exists
-
link_to_card "#{@set_name}+#{@card.rule_user_setting_name}", "(#{@state})",
-
target: "_blank"
-
end
-
end
-
-
1
def warning
-
if @set_name == "*all"
-
"This rule will affect all cards! Are you sure?"
-
else
-
narrower_warning
-
end
-
end
-
-
# warn user if rule change won't have a effect on the current card
-
# because there is a narrower rule
-
1
def narrower_warning
-
return unless @state.in? %i[current overwritten]
-
-
@narrower_rules << Card.fetch(@set_name).uncapitalized_label
-
return unless @state == :overwritten
-
-
narrower_warning_message
-
end
-
-
1
def narrower_warning_message
-
plural = @narrower_rules.size > 1 ? "s" : ""
-
"This rule will not have any effect on this card unless you delete " \
-
"the narrower rule#{plural} for #{@narrower_rules.to_sentence}."
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/rule_set_radio.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Rule; module RuleForm;
-
# Set: All rule cards (RuleForm, SetSelection)
-
#
-
1
module SetSelection;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/set_selection.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def bridge_rule_set_selection
-
wrap_with :div, class: "set-list" do
-
bridge_rule_set_formgroup
-
end
-
end
-
-
1
def bridge_rule_set_formgroup
-
tag = @rule_context.rule_user_setting_name
-
narrower = []
-
-
bridge_option_list "Set" do
-
rule_set_options.map do |set_name, state|
-
RuleSetRadio.new(self, set_name, tag, state).html narrower
-
end
-
end
-
end
-
-
1
def bridge_option_list title
-
index = -1
-
formgroup title, input: "set", class: "col-xs-6", help: false do
-
yield.inject("") do |res, radio|
-
index += 1
-
# TODO
-
if false # index.in? [2,3]
-
wrap_with(:li, radio, class: "radio") + res
-
else
-
wrap_with :ul do
-
wrap_with(:li, (radio + res), class: "radio")
-
end
-
end
-
end
-
end
-
end
-
-
1
def rule_set_options
-
@rule_set_options ||= @rule_context.set_options
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rule_form/set_selection.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Rule
-
# Set: All rule cards (Rules)
-
#
-
1
module Rules;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rules.rb"; end
-
1
event :save_recently_edited_settings, :integrate, on: :save, changed: %i[type content] do
-
10
if (recent = Card[:recent_settings])
-
10
recent.insert_item 0, name.right
-
10
attach_subcard recent
-
end
-
end
-
-
1
def rule_set_key
-
rule_set_name.key
-
end
-
-
1
def rule_set_name
-
if is_preference?
-
name.trunk_name.trunk_name
-
else
-
name.trunk_name
-
end
-
end
-
-
1
def rule_set_pattern_name
-
rule_set_name.tag_name
-
end
-
-
1
def rule_set
-
4
if is_preference?
-
self[0..-3]
-
else
-
4
trunk
-
end
-
end
-
-
1
def rule_setting
-
right
-
end
-
-
1
def rule_setting_name
-
name.tag
-
end
-
-
1
def short_help_text
-
Card[rule_setting_name].short_help_text
-
end
-
-
1
def rule_setting_title
-
rule_setting_name.tr "*", ""
-
end
-
-
1
def rule_user_setting_name
-
if is_preference?
-
"#{rule_user_name}+#{rule_setting_name}"
-
else
-
rule_setting_name
-
end
-
end
-
-
# ~~~~~~~~~~ determine the set options to which a user can apply the rule.
-
1
def set_options
-
@set_options ||= [].tap do |set_options|
-
set_option_candidates.each do |set_name|
-
set_options << [set_name, state_of_set(set_name)]
-
end
-
end
-
end
-
-
# the narrowest rule should be the one attached to the set being viewed.
-
# So, eg, if you're looking at the '*all plus' set, you shouldn't
-
# have the option to create rules based on arbitrary narrower sets, though
-
# narrower sets will always apply to whatever prototype we create
-
1
def first_set_option_index candidates
-
new_card? ? 0 : candidates.index { |c| c.to_name.key == rule_set_key }
-
end
-
-
1
def set_prototype
-
if is_preference?
-
self[0..-3].prototype
-
else
-
trunk.prototype
-
end
-
end
-
-
1
private
-
-
1
def set_option_candidates
-
candidates = set_prototype.set_names
-
first = first_set_option_index candidates
-
candidates[first..-1]
-
end
-
-
1
def state_of_set set_name
-
@sets_with_existing_rules ||= 0
-
if rule_for_set? set_name
-
@sets_with_existing_rules += 1
-
state_of_existing_set
-
else
-
state_of_nonexisting_set
-
end
-
end
-
-
1
def state_of_existing_set
-
@sets_with_existing_rules == 1 ? :current : :overwritten
-
end
-
-
1
def state_of_nonexisting_set
-
@sets_with_existing_rules == 1 ? :current : :overwritten
-
end
-
-
1
def rule_for_set? set_name
-
Card.exists?("#{set_name}+#{rule_user_setting_name}")
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/rule/rules.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptRules"
-
#
-
1
module ScriptRules;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/self/script_rules.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptMods.add_item :script_rules
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/self/script_rules.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Type
-
# Set: All "Set" cards
-
#
-
1
module Set;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set.rb"; end
-
1
include_set Type::SearchType
-
-
1
def anchor_name
-
name.left_name
-
end
-
-
1
def anchor
-
Card[anchor_name]
-
end
-
-
1
def pattern_name
-
name.tag_name
-
end
-
-
1
def pattern
-
4
tag
-
end
-
-
1
def inheritable?
-
junction_only? || (anchor_name&.junction? && self_set?)
-
end
-
-
1
def self_set?
-
pattern_name == Card::Set::Self.pattern.key
-
end
-
-
1
def subclass_for_set
-
4
current_set_pattern_code = pattern.codename
-
8
Card.set_patterns.find { |set| set.pattern_code == current_set_pattern_code }
-
end
-
-
1
def junction_only?
-
@junction_only.nil? ? (@junction_only = subclass_for_set.junction_only) : @junction_only
-
end
-
-
1
def label
-
klass = subclass_for_set
-
klass ? klass.label(anchor_name) : ""
-
end
-
-
1
def uncapitalized_label
-
label = label.to_s
-
return label unless label[0]
-
-
label[0] = label[0].downcase
-
label
-
end
-
-
1
def rule_cache_key_base
-
153
if (l = left) && (r = right)
-
82
"#{l.id}+#{Codename[r.id]}"
-
else
-
71
Codename[id].to_s
-
end
-
end
-
-
1
def all_user_ids_with_rule_for setting_code
-
153
Card::Rule.all_user_ids_with_rule_for self, setting_code
-
end
-
-
1
def setting_codenames_by_group
-
result = {}
-
Card::Setting.groups.each do |group, settings|
-
visible_settings =
-
settings.reject { |s| !s || !s.applies_to_cardtype(prototype.type_id) }
-
result[group] = visible_settings.map(&:codename) unless visible_settings.empty?
-
end
-
result
-
end
-
-
1
def visible_setting_codenames
-
@visible_setting_codenames ||= visible_settings.map(&:codename)
-
end
-
-
1
def visible_settings group=nil, cardtype_id=nil
-
cardtype_id ||= prototype.type_id
-
settings =
-
(group && Card::Setting.groups[group]) || Card::Setting.groups.values.flatten.compact
-
settings.reject do |setting|
-
!setting || !setting.applies_to_cardtype(cardtype_id)
-
end
-
end
-
-
1
def broader_sets
-
prototype.set_names[1..-1]
-
end
-
-
1
def prototype
-
opts = subclass_for_set.prototype_args anchor_name
-
Card.fetch opts[:name], new: opts
-
end
-
-
1
def prototype_default_type_id
-
prototype_default_card.type_id
-
end
-
-
1
def prototype_default_card
-
prototype.rule_card(:default)
-
end
-
-
1
def related_sets with_self=false
-
if subclass_for_set.anchorless?
-
prototype.related_sets with_self
-
else
-
left(new: {}).related_sets with_self
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Type; module Set;
-
# Set: All "Set+HtmlViews" cards (HtmlViews)
-
#
-
1
module HtmlViews;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/html_views.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
before :open do
-
voo.hide :template_closer
-
end
-
-
1
view :core, cache: :never do
-
filtered_rule_list :bar_rule_list
-
end
-
-
1
view :nest_rules, cache: :never, unknown: true, wrap: :slot do
-
filtered_rule_list :quick_edit_rule_list, :field_related_rules, :related, mark: ""
-
end
-
-
1
view :modal_nest_rules, cache: :never, unknown: true,
-
wrap: { modal: { title: "Rules for nest" } } do
-
filtered_rule_list :quick_edit_rule_list, :field_related_rules, :self
-
end
-
-
1
view :bridge_rules_tab, cache: :never do
-
filtered_rule_list :pill_rule_list, :common, :related, mark: ""
-
end
-
-
1
def filtered_rule_list view, *filter_args
-
[rules_filter(view, *filter_args),
-
render(view)]
-
end
-
-
1
view :set_label do
-
wrap_with :strong, card.label, class: "set-label"
-
end
-
-
1
Card::Setting.groups.each_key do |group_key|
-
7
view group_key.to_sym do
-
next unless card.visible_settings(group_key).present?
-
-
haml :group_panel, group_key: group_key
-
end
-
end
-
-
1
def setting_group default=:common
-
voo&.filter&.to_sym || params[:group]&.to_sym || default
-
end
-
-
1
view :input do
-
"Cannot currently edit Sets" # LOCALIZE
-
end
-
-
1
view :one_line_content, wrap: {} do
-
""
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/html_views.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class Type; module Set;; module HtmlViews;
-
# Set: All "Set+HtmlViews" cards (HtmlViews, RuleLists)
-
#
-
1
module RuleLists;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/html_views/rule_lists.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :quick_edit_rule_list, cache: :never, wrap: { slot: { class: "rule-list" } } do
-
quick_edit_rule_list setting_list_from_params(:field_related)
-
end
-
-
1
view :bar_rule_list, cache: :never, wrap: { slot: { class: "rule-list" } } do
-
bar_rule_list setting_list_from_params
-
end
-
-
1
view :pill_rule_list, cache: :never, wrap: { slot: { class: "rule-list" } } do
-
pill_rule_list setting_list_from_params
-
end
-
-
1
def quick_edit_rule_list settings
-
list_tag class: "nav nav-pills flex-column bridge-pills" do
-
settings.map { |setting| rule_list_item setting, :quick_edit }
-
end
-
end
-
-
1
def pill_rule_list settings
-
list_items =
-
settings.map { |setting| rule_list_item setting, :rule_bridge_link }
-
bridge_pills list_items
-
end
-
-
1
def bar_rule_list settings
-
list_items =
-
settings.map { |setting| rule_list_item setting, :bar, hide: :full_name }
-
list_items.join("\n").html_safe
-
end
-
-
1
def rule_list_item setting, view, opts={}
-
return "" unless show_view? setting
-
-
rule_card = card.fetch setting, new: {}
-
nest(rule_card, opts.merge(view: view)).html_safe
-
end
-
-
1
def setting_list_from_params default=:common
-
setting_list setting_group(default)
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/html_views/rule_lists.rb ~~
-
# -*- encoding : utf-8 -*-
-
5
class Card; module Set; class Type; module Set;; module HtmlViews;
-
# Set: All "Set+HtmlViews" cards (HtmlViews, Template)
-
#
-
1
module Template;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/html_views/template.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :template_link, cache: :never do
-
wrap do
-
voo.title = parent.voo.nest_syntax if parent
-
"{{#{link_to_template_editor}}}"
-
end
-
end
-
-
1
def link_to_template_editor
-
link_to_view :modal_nest_rules, voo.title
-
end
-
end
-
end;end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/html_views/template.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Type; module Set;
-
# Set: All "Set+RulesFilter" cards (RulesFilter)
-
#
-
1
module RulesFilter;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/rules_filter.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def rules_filter view, selected_setting=nil, set_options=nil, path_opts={}
-
form_tag path(path_opts.merge(view: view)),
-
remote: true, method: "get", role: "filter",
-
"data-slot-selector": ".card-slot.rule-list",
-
class: classy("nodblclick slotter form-inline slim-select2 m-2") do
-
output [
-
label_tag(:view, icon_tag("filter_list"), class: "mr-2"),
-
setting_select(selected_setting),
-
set_select(set_options)
-
].flatten
-
end
-
end
-
-
1
def set_select set_options
-
return filter_text.html_safe unless set_options
-
-
[content_tag(:span, "rules that apply to set ...", class: "mx-2 small"),
-
set_select_tag(set_options)]
-
end
-
-
1
def setting_select selected=nil
-
select_tag(:group, grouped_options_for_select(setting_options, selected),
-
class: "_submit-on-select form-control",
-
"data-select2-id": "#{unique_id}-#{Time.now.to_i}")
-
end
-
-
1
def filter_text
-
wrap_with :span, class: "mx-2 small" do
-
"rules that apply to #{_render_set_label.downcase}" # LOCALIZE
-
end
-
end
-
-
1
def set_select_tag set_options=:related
-
select_tag(:mark, set_select_options(set_options),
-
class: "_submit-on-select form-control _close-rule-overlay-on-select",
-
"data-minimum-results-for-search": "Infinity",
-
"data-select2-id": "#{unique_id}-#{Time.now.to_i}")
-
end
-
-
1
def selected_set
-
params[:set]
-
end
-
-
1
def set_select_options set_options
-
options =
-
if set_options == :related
-
related_set_options
-
else
-
[[card.label, card.name.url_key]]
-
end
-
options_for_select(options, selected_set)
-
end
-
-
1
def related_set_options
-
card.related_sets(true).map do |name, label|
-
[label, name.to_name.url_key]
-
end
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/rules_filter.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class Type; module Set;
-
# Set: All "Set+SettingLists" cards (SettingLists)
-
#
-
1
module SettingLists;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/setting_lists.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
SETTING_OPTIONS = [["Common", :common_rules],
-
["All", :all_rules],
-
["Field", :field_related_rules],
-
["Recent", :recent_rules]].freeze
-
-
1
COMMON_SETTINGS = %i[create read update delete structure default guide].freeze
-
1
FIELD_SETTINGS = %i[default help].freeze
-
-
1
def setting_options
-
[["Categories", SETTING_OPTIONS],
-
["Groups", Card::Setting.group_names.keys],
-
["Single rules", card.visible_setting_codenames]]
-
end
-
-
1
def field_settings
-
%i[default help input_type content_options content_option_view]
-
end
-
-
# @param val setting category, setting group or single setting
-
1
def setting_list val
-
category_setting_list(val) || group_setting_list(val) || [val]
-
end
-
-
1
def group_setting_list group
-
card.visible_settings(group).map(&:codename) if Card::Setting.groups[group]
-
end
-
-
1
def category_setting_list cat
-
case cat
-
when :all, :all_rules
-
card.visible_setting_codenames.sort
-
when :recent, :recent_rules
-
recent_settings
-
when :common, :common_rules
-
card.visible_setting_codenames & COMMON_SETTINGS
-
when :field_related, :field_related_rules
-
field_related_settings
-
when :nest_editor_field_related
-
nest_editor_field_related_settings
-
end
-
end
-
-
1
def nest_editor_field_related_settings
-
field_settings
-
# & card.visible_settings(nil, card.prototype_default_type_id).map(&:codename)
-
end
-
-
1
def field_related_settings
-
field_settings # card.visible_setting_codenames &
-
end
-
-
1
def recent_settings
-
recent_settings = Card[:recent_settings].item_cards.map(&:codename)
-
recent_settings.map(&:to_sym) & card.visible_setting_codenames
-
end
-
-
1
view :all_rules_list do
-
pill_rule_list card.visible_setting_codenames.sort
-
end
-
-
1
view :recent_rules_list do
-
recent_settings = Card[:recent_settings].item_cards.map(&:codename)
-
settings = recent_settings.map(&:to_sym) & card.visible_setting_codenames
-
pill_rule_list settings
-
end
-
-
1
view :common_rules_list do
-
settings = card.visible_setting_codenames & COMMON_SETTINGS # "&" = set intersection
-
pill_rule_list settings
-
end
-
-
1
view :field_related_rules_list do
-
pill_rule_list field_related_settings
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-rules/set/type/set/setting_lists.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (ReferenceEditor)
-
#
-
# shared helper methods for link editor and nest editor
-
1
module ReferenceEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor.rb"; end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def tinymce_id
-
params[:tinymce_id]
-
end
-
-
1
def tm_param key
-
params[:"tm_snippet_#{key}"]
-
end
-
-
1
def modal_tm_snippet_editor?
-
@tm_snippet_editor_mode != :overlay
-
end
-
-
1
private
-
-
1
def apply_tm_snippet_data snippet
-
{ "data-tinymce-id": tinymce_id }.tap do |data|
-
apply_tm_snippet_var(data, :start) { tm_param :start }
-
apply_tm_snippet_var(data, :size, :raw) { snippet.raw.size }
-
data["data-dismiss"] = "modal" if modal_tm_snippet_editor?
-
data["data-index"] = params["index"] if params["index"].present?
-
end
-
end
-
-
1
def apply_tm_snippet_var data, varname, paramname=nil
-
return unless tm_param(paramname || varname).present?
-
-
data[:"data-tm-snippet-#{varname}"] = yield
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module ReferenceEditor;
-
# Set: All cards (ReferenceEditor, LinkEditor)
-
#
-
1
module LinkEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/link_editor.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :link_editor, cache: :never, unknown: true,
-
wrap: {
-
slot: { class: "_overlay d0-card-overlay card nodblclick" }
-
} do
-
link_editor :overlay
-
end
-
-
1
view :modal_link_editor, cache: :never, unknown: true,
-
wrap: { slot: { class: "nodblclick" } } do
-
modal_link_editor
-
end
-
-
1
def link_editor editor_mode
-
@tm_snippet_editor_mode = editor_mode
-
haml :reference_editor, ref_type: :link, editor_mode: @tm_snippet_editor_mode,
-
apply_opts: link_apply_opts, snippet: link_snippet
-
end
-
-
1
def modal_link_editor
-
wrap_with :modal do
-
link_editor :modal
-
end
-
end
-
-
1
def link_snippet
-
@link_snippet ||= LinkParser.new params[:tm_snippet_raw]
-
end
-
-
1
def link_apply_opts
-
apply_tm_snippet_data link_snippet
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/link_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module ReferenceEditor;
-
# Set: All cards (ReferenceEditor, LinkEditor)
-
#
-
#! no set module
-
-
1
module LinkEditor;
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/link_editor/link_parser.rb"; end
-
# Extracts all information needed to generate the link editor form
-
# from a link syntax string
-
1
class LinkParser
-
1
attr_reader :name, :options, :field, :raw
-
-
1
def self.new link_string
-
return super if link_string.is_a? String
-
-
OpenStruct.new(name: "", options: {}, raw: "[[ ]]")
-
end
-
-
1
def initialize link_string
-
@raw = link_string
-
link = Card::Content::Chunk::Link.new link_string, nil
-
init_name link.name
-
@options = link.options
-
end
-
-
1
def title
-
@options && @options[:title]
-
end
-
-
1
def field?
-
@field
-
end
-
-
1
private
-
-
1
def init_name name
-
@field = name.to_name.simple_relative?
-
@name = @field ? name.to_s[1..-1] : name
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/link_editor/link_parser.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module ReferenceEditor;
-
# Set: All cards (ReferenceEditor, NestEditor)
-
#
-
1
module NestEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/nest_editor.rb"; end
-
-
1
def left_type_for_nest_editor_set_selection
-
type_name
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
# Card::View::Options.shark_keys - %i[nest_syntax nest_name items cache]
-
# TODO: connect to Card::View::Options
-
# (that way a mod can add an option that becomes available to nests)
-
-
1
view :nest_editor, cache: :never, unknown: true,
-
wrap: {
-
slot: { class: "_overlay d0-card-overlay card nodblclick" }
-
} do
-
nest_editor :overlay
-
end
-
-
1
view :modal_nest_editor, cache: :never, unknown: true,
-
wrap: { slot: { class: "nodblclick" } } do
-
modal_nest_editor
-
end
-
-
1
view :nest_content, perms: :create, cache: :never, unknown: true, wrap: :slot do
-
if card.known?
-
known_nest_content
-
else
-
unknown_nest_content
-
end
-
end
-
-
1
def nest_editor editor_mode
-
@tm_snippet_editor_mode = editor_mode
-
voo.hide :content_tab unless show_content_tab?
-
haml :reference_editor, ref_type: :nest, editor_mode: @tm_snippet_editor_mode,
-
apply_opts: nest_apply_opts,
-
snippet: nest_snippet
-
end
-
-
1
def nest_editor_tabs
-
tab_hash = {}
-
tab_hash[:content] = nest_content_tab if voo.show? :content_tab
-
tab_hash.merge! options: haml(:_options, snippet: nest_snippet),
-
rules: nest_rules_tab,
-
help: haml(:_help)
-
tabs tab_hash, default_active_tab
-
end
-
-
1
def show_content_tab?
-
!card.is_structure?
-
end
-
-
1
def default_active_tab
-
voo.show?(:content_tab) ? :content : :options
-
end
-
-
1
def nest_content_tab
-
name_dependent_slot do
-
@nest_content_tab || nest(card.name.field(nest_snippet.name),
-
view: :nest_content, hide: :guide)
-
end
-
end
-
-
1
def nest_rules_tab
-
name_dependent_slot do
-
nest(set_name_for_nest_rules, view: :nest_rules)
-
end
-
end
-
-
1
def name_dependent_slot
-
result = [empty_nest_name_alert(nest_snippet.name.blank?)]
-
result <<
-
if nest_snippet.name.blank?
-
content_tag :div, "", class: "card-slot" # placeholder
-
else
-
yield
-
end
-
result
-
end
-
-
1
def empty_nest_name_alert show
-
alert :warning, false, false,
-
class: "mb-0 _empty-nest-name-alert #{'d-none' unless show}" do
-
"nest name required" # LOCALIZE
-
end
-
end
-
-
1
def modal_nest_editor
-
wrap_with :modal do
-
nest_editor :modal
-
end
-
end
-
-
1
def nest_snippet
-
@nest_snippet ||=
-
Card::Reference::NestParser.new params[:tm_snippet_raw],
-
default_nest_view, default_item_view
-
end
-
-
1
def set_name_for_nest_rules
-
nest_name = nest_snippet.name
-
if (type_name = card.left_type_for_nest_editor_set_selection)
-
[type_name, nest_name, :type_plus_right]
-
else
-
[nest_name, :right]
-
end
-
end
-
-
1
def default_nest_editor_item_options
-
[[:view, default_item_view]]
-
end
-
-
1
def nest_option_name_select selected=nil, level=0
-
classes = "form-control form-control-sm _nest-option-name"
-
classes += " _new-row" unless selected
-
select_tag "nest_option_name_#{unique_id}",
-
nest_option_name_select_options(selected, level),
-
class: classes, id: nil
-
# id: nil ensures that select2 generates its own unique identifier
-
# that ensures that we can clone this tag without breaking select2
-
end
-
-
1
def nest_option_name_select_options selected, level
-
options = selected ? [] : ["--"]
-
options += Card::Reference::NestParser::NEST_OPTIONS
-
options_for_select(
-
options, disabled: nest_option_name_disabled(selected, level),
-
selected: selected
-
)
-
end
-
-
1
def nest_option_name_disabled selected, level
-
disabled = nest_option_name_disabled_options level
-
disabled = disabled&.map(&:first)
-
disabled&.delete selected if selected
-
disabled
-
end
-
-
1
def nest_option_name_disabled_options level
-
if level == 0
-
nest_snippet.options
-
else
-
nest_snippet.item_options[level - 1] || default_nest_editor_item_options
-
end
-
end
-
-
1
def nest_apply_opts
-
apply_tm_snippet_data nest_snippet
-
end
-
-
1
def nest_option_value_select value=nil
-
# select_tag "nest_option_value_#{unique_id}"
-
text_field_tag "value", value,
-
class: "_nest-option-value form-control form-control-sm",
-
disabled: !value,
-
id: nil
-
end
-
-
1
def known_nest_content
-
voo.hide! :cancel_button
-
add_name_context
-
with_nest_mode :edit do
-
frame do
-
[
-
render_edit_inline
-
]
-
end
-
end
-
end
-
-
1
def unknown_nest_content
-
voo.hide! :guide
-
voo.show! :new_type_formgroup
-
new_view_frame_and_form buttons: new_image_buttons,
-
success: { tinymce_id: Env.params[:tinymce_id] }
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/nest_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
4
class Card; module Set; class All; module ReferenceEditor;
-
# Set: All cards (ReferenceEditor, NestImage)
-
#
-
1
module NestImage;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/nest_image.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :nest_image, unknown: true, cache: :never,
-
wrap: {
-
slot: { class: "_overlay d0-card-overlay card nodblclick" }
-
} do
-
nest_image_editor :overlay
-
end
-
-
1
view :modal_nest_image, unknown: true, cache: :never,
-
wrap: { slot: { class: "nodblclick" } } do
-
nest_image_editor :modal
-
end
-
-
1
view :new_image, perms: :create, unknown: true, cache: :never do
-
new_view_frame_and_form new_image_form_opts
-
end
-
-
1
def nest_image_editor editor_mode
-
adapt_reference_editor_for_images
-
nest_editor editor_mode
-
end
-
-
-
1
def adapt_reference_editor_for_images
-
nest_name = card.autoname(card.name.field("image01"))
-
voo.show! :content_tab
-
@nest_content_tab = nest(nest_name, view: :new_image, type: :image, hide: :guide)
-
-
image_name = nest_name.to_name.right
-
@nest_snippet = Card::Reference::NestParser.new_image image_name
-
end
-
-
-
1
def new_image_form_opts
-
{ buttons: new_image_buttons,
-
success: { tinymce_id: Env.params[:tinymce_id],
-
view: :open } }
-
end
-
-
1
def new_image_buttons
-
button_formgroup do
-
[standard_save_button(no_origin_update: true, class: "_change-create-to-update")]
-
end
-
end
-
end
-
-
2
module JsFormat; module_parent.send :register_set_format, Card::Format::JsFormat, self; extend Card::Set::AbstractFormat
-
1
view :change_create_to_update, unknown: true do
-
tm_id = if Env.params[:tinymce_id].present?
-
"\"#{Env.params[:tinymce_id]}\""
-
else
-
'$(".tinymce-textarea").attr("id")'
-
end
-
<<-JAVASCRIPT.strip_heredoc
-
nest.changeCreateToUpdate(#{tm_id});
-
JAVASCRIPT
-
end
-
-
1
view :open_nest_editor, unknown: true do
-
tm_id = if Env.params[:tinymce_id].present?
-
"\"#{Env.params[:tinymce_id]}\""
-
else
-
'$(".tinymce-textarea").attr("id")'
-
end
-
<<-JAVASCRIPT.strip_heredoc
-
tm = tinymce.get(#{tm_id});
-
nest.insertNest(tm, "{{+#{card.name.tag}|view: content; size: medium}}");
-
JAVASCRIPT
-
end
-
end
-
end;end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/reference_editor/nest_image.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (TinymceEditor)
-
#
-
1
module TinymceEditor;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/tinymce_editor.rb"; end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
def tinymce_editor_input
-
7
text_area :content, rows: 3, class: "tinymce-textarea d0-card-content",
-
id: unique_id
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/all/tinymce_editor.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptTinymce"
-
#
-
1
module ScriptTinymce;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/self/script_tinymce.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptMods.add_item :script_tinymce
-
1
Self::InputOptions.add_to_basket :options, "tinymce editor"
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/self/script_tinymce.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "ScriptTinymceConfig"
-
#
-
1
module ScriptTinymceConfig;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/self/script_tinymce_config.rb"; end
-
1
include_set Abstract::CodeFile
-
-
1
Self::ScriptEditors.add_item :script_tinymce_config
-
1
All::Head::HtmlFormat.add_to_basket :mod_js_config, [:tiny_mce, "setTinyMCEConfig"]
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/self/script_tinymce_config.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Self
-
# Set: The card "TinyMce"
-
#
-
1
module TinyMce;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/self/tiny_mce.rb"; end
-
1
def raw_help_text
-
<<-TEXT
-
Configure [[http://tinymce.com|TinyMCE]], Decko's default
-
[[http://en.wikipedia.org/wiki/Wysiwyg|wysiwyg]] editor.
-
[[http://decko.org/TinyMCE|more]]
-
TEXT
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-tinymce_editor/set/self/tiny_mce.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (EventViz)
-
#
-
# the events method is a developer's tool for visualizing the event order
-
# for a given card.
-
# For example, from a console you might run
-
#
-
# puts mycard.events :update
-
#
-
# to see the order of events that will be executed on mycard.
-
1
module EventViz;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-monkey/set/all/event_viz.rb"; end
-
# The indention and arrows (^v) indicate event dependencies.
-
#
-
# Note: as of yet, the functionality is a bit rough. It does not display events
-
# that are called directly from within other events,
-
# and certain event requirements (like the presence of an 'act') may
-
# prevent events from showing up in the tree.
-
1
def events action
-
@action = action
-
events = Director::Stages::STAGES.map { |stage| events_tree "#{stage}_stage" }
-
@action = nil
-
print_events events
-
end
-
-
1
def events_tree filt
-
try("_#{filt}_callbacks")&.each_with_object({ name: filt }) do |callback, hash|
-
events_branch hash, callback.kind, callback.filter if callback.applies? self
-
end
-
end
-
-
1
private
-
-
1
def print_events events, prefix="", depth=0
-
depth += 1
-
space = " " * (depth * 2)
-
text = ""
-
events.each do |event|
-
text += print_event_pre event, depth, space
-
text += print_event_main event, prefix
-
text += print_event_post event, depth, space
-
end
-
text
-
end
-
-
1
def print_event_pre event, depth, space
-
if event[:before]
-
print_events event[:before], space + "v ", depth
-
elsif event[:around]
-
print_events event[:around], space + "vv ", depth
-
else
-
""
-
end
-
end
-
-
1
def print_event_main event, prefix
-
"#{prefix}#{event[:name]}\n"
-
end
-
-
1
def print_event_post event, depth, space
-
return "" unless event[:after]
-
-
print_events event[:after], space + "^ ", depth
-
end
-
-
1
def events_branch hash, kind, filter
-
hash[kind] ||= []
-
hash[kind] << events_tree(filter)
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-monkey/set/all/event_viz.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class All
-
# Set: All cards (ViewViz)
-
#
-
1
module ViewViz;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-monkey/set/all/view_viz.rb"; end
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :views_by_format do
-
format_views =
-
self.class.ancestors.each_with_object({}) do |format_class, hash|
-
views =
-
format_class.instance_methods.map do |method|
-
next unless method.to_s =~ /^_view_(.+)$/
-
Regexp.last_match(1)
-
end.compact
-
next unless views.present?
-
format_class.name =~ /^Card(::Set)?::(.+?)$/ #::(\w+Format)
-
hash[Regexp.last_match(2)] = views
-
end
-
accordion_group format_views
-
end
-
-
1
view :views_by_name do
-
views = methods.map do |method|
-
Regexp.last_match(1) if method.to_s.match?(/^_view_(.+)$/)
-
end.compact.sort
-
list_group views
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-monkey/set/all/view_viz.rb ~~
-
# -*- encoding : utf-8 -*-
-
3
class Card; module Set; class Right
-
# Set: All "+Debug" cards
-
#
-
1
module Debug;
-
1
extend Card::Set
-
1
def self.source_location; "/Users/ezl5238/dev/decko/gem/card-mod-monkey/set/right/debug.rb"; end
-
1
def virtual?
-
new?
-
end
-
-
2
module HtmlFormat; module_parent.send :register_set_format, Card::Format::HtmlFormat, self; extend Card::Set::AbstractFormat
-
1
view :core do
-
core_section_config(card.left).map do |item|
-
section(*item)
-
end
-
end
-
-
1
def core_section_config subject
-
[["Sets", tabs("set modules" => set_modules_accordion(subject),
-
"all modules" => singleton_modules_list(subject),
-
"patterns" => set_patterns_breadcrumb(subject))],
-
["Views", tabs("by format" => subformat(subject)._render_views_by_format,
-
"by name" => subformat(subject)._render_views_by_name)],
-
["Events", tabs(create: "<pre>#{subject.events(:create)}</pre>",
-
update: "<pre>#{subject.events(:update)}</pre>",
-
delete: "<pre>#{subject.events(:delete)}</pre>")],
-
["Cache/DB Comparison", cache_comparison_table(subject)]]
-
end
-
-
# rubocop:disable AccessorMethodName
-
1
def set_modules_accordion subject
-
sets = subject.set_modules.each_with_object({}) do |sm, hash|
-
ans = sm.ancestors
-
ans.shift
-
hash[sm.to_s] = ans
-
end
-
accordion_group sets
-
end
-
-
1
def set_patterns_breadcrumb subject
-
links = subject.patterns.reverse.map { |pattern| link_to_card pattern.to_s }
-
breadcrumb links
-
end
-
# rubocop:enable AccessorMethodName
-
-
1
def singleton_modules_list subject
-
all_mods = subject.singleton_class.ancestors.map(&:to_s)
-
all_mods.shift
-
list_group all_mods
-
end
-
-
1
def cache_comparison_table subject
-
cache_card = Card.fetch(subject.key)
-
db_card = Card.find_by_key(subject.key)
-
return unless cache_card && db_card
-
table(
-
%i[name updated_at updater_id content inspect].map do |field|
-
[field.to_s,
-
h(cache_card.send(field)),
-
h(db_card.send(field))]
-
end,
-
header: ["Field", "Cache Val", "Database Val"]
-
)
-
end
-
-
1
def section title, content
-
%(
-
<h2>#{title}</h2>
-
#{content}
-
)
-
end
-
-
1
def class_locations klass
-
methods = defined_methods(klass)
-
file_groups = methods.group_by { |sl| sl[0] }
-
file_counts = file_groups.map do |file, sls|
-
lines = sls.map { |sl| sl[1] }
-
count = lines.size
-
line = lines.min
-
{ file: file, count: count, line: line }
-
end
-
file_counts.sort_by! { |fc| fc[:count] }
-
file_counts.map { |fc| [fc[:file], fc[:line]] }
-
end
-
-
1
def defined_methods klass
-
methods =
-
klass.methods(false).map { |m| klass.method(m) } +
-
klass.instance_methods(false).map { |m| klass.instance_method(m) }
-
methods.map!(&:source_location)
-
methods.compact!
-
methods
-
end
-
end
-
end;end;end;end;
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card-mod-monkey/set/right/debug.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: All
-
#
-
1
class Card::Set::All < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
1
def label _name
-
140
"All cards"
-
end
-
-
1
def short_label _name
-
"everything"
-
end
-
-
1
def prototype_args _anchor
-
{}
-
end
-
end
-
1
register "All".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/01_all.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: AllPlus
-
#
-
1
class Card::Set::AllPlus < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
1
@@options = { junction_only: true }
-
-
1
def label _name
-
'All "+" cards'
-
end
-
-
1
def short_label _name
-
'all "+" cards'
-
end
-
-
1
def prototype_args _anchor
-
{ name: "+" }
-
end
-
end
-
1
register "AllPlus".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/02_all_plus.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: Type
-
#
-
1
class Card::Set::Type < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
1
load "card/set/type.rb" # "load" not "require" so pattern reloads properly
-
-
1
def label name
-
53
%(All "#{name}" cards)
-
end
-
-
1
def short_label name
-
%(all "#{name}s")
-
end
-
-
1
def generic_label
-
"cards of a given type"
-
end
-
-
1
def prototype_args anchor
-
{ type: anchor }
-
end
-
-
1
def pattern_applies? card
-
4940
!!card.type_id
-
end
-
-
1
def anchor_name card
-
4406
card.type_name
-
end
-
-
1
def anchor_id card
-
4406
card.type_id
-
end
-
end
-
1
register "Type".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/03_type.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: Star
-
#
-
1
class Card::Set::Star < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
1
def label _name
-
'All "*" cards'
-
end
-
-
1
def short_label _name
-
'all "*" cards'
-
end
-
-
1
def prototype_args _anchor
-
{ name: "*dummy" }
-
end
-
-
1
def pattern_applies? card
-
4940
card.name.star?
-
end
-
end
-
1
register "Star".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/04_star.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: Rstar
-
#
-
1
class Card::Set::Rstar < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
1
@@options = { junction_only: true }
-
-
1
def label _name
-
1
'All "+*" cards'
-
end
-
-
1
def short_label _name
-
'all "+*" cards'
-
end
-
-
1
def prototype_args _anchor
-
{ name: "*dummy+*dummy" }
-
end
-
-
1
def pattern_applies? card
-
4940
card.name.rstar?
-
end
-
end
-
1
register "Rstar".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/05_rstar.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: Rule
-
#
-
1
class Card::Set::Rule < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
1
@@options = { junction_only: true }
-
-
1
def label _name
-
11
"All rule cards"
-
end
-
-
1
def short_label _name
-
"all rule cards"
-
end
-
-
1
def prototype_args _anchor
-
{ name: "*all+*create" }
-
end
-
-
1
def pattern_applies? card
-
4940
card.is_rule?
-
end
-
end
-
1
register "Rule".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/06_rule.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: Right
-
#
-
1
class Card::Set::Right < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
@@options = {
-
1
junction_only: true,
-
assigns_type: true
-
}
-
-
1
def label name
-
60
%(All "+#{name}" cards)
-
end
-
-
1
def short_label name
-
%(all "+#{name}s")
-
end
-
-
1
def generic_label
-
"given field cards"
-
end
-
-
1
def prototype_args anchor
-
{ name: "*dummy+#{anchor}" }
-
end
-
-
1
def anchor_name card
-
1657
card.name.tag
-
end
-
end
-
1
register "Right".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/07_right.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: TypePlusRight
-
#
-
# Patterned field names on a specific type
-
1
class Card::Set::TypePlusRight < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
-
@@options = {
-
1
junction_only: true,
-
assigns_type: true,
-
anchor_parts_count: 2
-
}
-
-
1
def label name
-
4
name = name.to_name
-
4
%(All "+#{name.tag}" cards on "#{name.left}" cards)
-
end
-
-
1
def short_label name
-
name = name.to_name
-
%(all "+#{name.tag}" on "#{name.left}s")
-
end
-
-
1
def generic_label
-
"given field cards on a given type"
-
end
-
-
1
def prototype_args anchor
-
{
-
name: "+#{anchor.tag}",
-
supercard: Card.new(name: "*dummy", type: anchor.trunk_name)
-
}
-
end
-
-
1
def anchor_name card
-
1657
"#{left_type(card)}+#{card.name.tag}"
-
end
-
end
-
1
register "TypePlusRight".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/08_type_plus_right.rb ~~
-
# -*- encoding : utf-8 -*-
-
# Set Pattern: Self
-
#
-
1
class Card::Set::Self < Card::Set::Pattern::Base
-
1
extend Card::Set::Pattern::Helper
-
1
cattr_accessor :options
-
1
class << self
-
1
def label name
-
102
%(The card "#{name}")
-
end
-
-
1
def short_label name
-
4
name
-
end
-
-
1
def generic_label
-
"a single card"
-
end
-
-
1
def prototype_args anchor
-
{ name: anchor }
-
end
-
-
1
def anchor_name card
-
4940
card.name
-
end
-
-
1
def anchor_id card
-
4940
card.id
-
end
-
end
-
1
register "Self".underscore.to_sym, (options || {})
-
end
-
-
# ~~ generated from /Users/ezl5238/dev/decko/gem/card/mod/core/set_pattern/09_self.rb ~~
-
1
module Decko
-
# methods for managing decko responses
-
1
module Response
-
1
def response_format
-
33
@response_format ||= format_name_from_params
-
end
-
-
1
private
-
-
1
def respond format, result, status
-
33
if status.in? [302, 303]
-
1
hard_redirect result
-
32
elsif format.is_a?(Card::Format::FileFormat) && status == 200
-
1
send_file(*result)
-
else
-
31
render_response result.to_s.html_safe, status, format.mime_type
-
end
-
end
-
-
1
def render_response body, status, content_type
-
31
render body: body, status: status, content_type: content_type
-
end
-
-
1
def redirect_cud_success success
-
13
redirect_type = success.redirect || default_cud_success_redirect_type
-
13
if redirect_type.to_s == "soft"
-
7
success.target ||= self
-
7
soft_redirect success
-
else
-
6
hard_redirect success.to_url, 303
-
end
-
end
-
-
1
def default_cud_success_redirect_type
-
10
Card::Env.ajax? ? "soft" : "hard"
-
end
-
-
# return a redirect response
-
1
def hard_redirect url, status=302
-
8
url = card_url url # make sure we have absolute url
-
8
if Card::Env.ajax?
-
# lets client reset window location
-
# (not just receive redirected response)
-
# formerly used 303 response, but that gave IE the fits
-
render json: { redirect: url }
-
else
-
8
redirect_to url, status: status
-
end
-
end
-
-
# return a standard GET response directly.
-
# Used in AJAX situations where PRG pattern is unwieldy
-
1
def soft_redirect success
-
# Card::Cache.renew
-
7
@card = success.target
-
7
require_card_for_soft_redirect!
-
7
self.params = Card::Env[:params] = soft_redirect_params
-
7
load_action
-
7
show
-
end
-
-
1
def reload
-
render json: { reload: true }
-
end
-
-
1
def soft_redirect_params
-
7
new_params = params.clone
-
7
new_params.delete :card
-
7
new_params.delete :action
-
7
new_params.merge Card::Env.success.params
-
end
-
-
1
def require_card_for_soft_redirect!
-
7
return if card.is_a? Card
-
raise Card::Error, "tried to do soft redirect without a card"
-
end
-
-
# (obviously) deprecated
-
1
def send_deprecated_asset
-
2
filename = [params[:mark], params[:format]].compact.join(".")
-
2
send_file asset_file_path(filename), x_sendfile: true
-
end
-
-
1
def asset_file_path filename
-
2
path = Decko::Engine.paths["gem-assets"].existent.first
-
2
path = File.join path, filename
-
2
validate_path filename, path
-
1
path
-
end
-
-
1
def validate_path filename, path
-
# for security, block relative paths
-
2
raise Card::Error::BadAddress if filename.include?("../") || !::File.exist?(path)
-
end
-
-
# TODO: everything below should go in a separate file
-
# below is about beginning (initialization). above is about end (response)
-
# Both this file and that would make sense as submodules of CardController
-
-
1
def load_format
-
33
request.format = :html if implicit_html?
-
33
card.format response_format
-
end
-
-
1
def implicit_html?
-
33
(Card::Env.ajax? && !params[:format]) || request.format.to_s == "*/*"
-
end
-
-
1
def format_name_from_params
-
28
if explicit_file_format? then :file
-
27
elsif params[:format].present? then params[:format].to_sym
-
26
else request.format.to_sym
-
end
-
end
-
-
1
def explicit_file_format?
-
28
params[:explicit_file] || !Card::Format.registered.member?(request.format)
-
end
-
-
1
def interpret_mark mark
-
23
case mark
-
when "*previous"
-
# Why support this? It's only needed in Success, right? Deprecate?
-
1
return hard_redirect(Card::Env.previous_location)
-
when nil
-
5
implicit_mark
-
else
-
17
explicit_mark mark
-
end
-
end
-
-
1
def explicit_mark mark
-
# we should find the place where we produce these bad urls
-
17
mark.valid_encoding? ? mark : mark.force_encoding("ISO-8859-1").encode("UTF-8")
-
end
-
-
1
def implicit_mark
-
case
-
5
when initial_setup then ""
-
2
when (name = params.dig :card, :name) then name
-
3
when view_does_not_require_name? then ""
-
else home_mark
-
end
-
end
-
-
1
def home_mark
-
Card::Rule.global_setting(:home) || "Home"
-
end
-
-
1
def view_does_not_require_name?
-
3
return false unless (view = params[:view]&.to_sym)
-
3
Card::Set::Format::AbstractFormat::ViewOpts.unknown_ok[view]
-
end
-
-
# alters params
-
1
def initial_setup
-
5
return unless initial_setup?
-
prepare_setup_card!
-
end
-
-
1
def initial_setup?
-
5
Card::Auth.needs_setup? && Card::Env.html?
-
end
-
-
1
def prepare_setup_card!
-
params[:card] = { type_id: Card.default_accounted_type_id }
-
params[:view] = "setup"
-
end
-
end
-
end
-
1
class ApplicationController < ActionController::Base
-
end
-
# -*- encoding : utf-8 -*-
-
-
# Decko's only controller.
-
1
class CardController < ApplicationController
-
1
include ::Card::Env::Location
-
1
include ::Recaptcha::Verify
-
1
include ::Decko::Response
-
-
1
layout nil
-
1
attr_reader :card
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# PUBLIC METHODS
-
-
1
def create
-
22
handle { card.save! }
-
end
-
-
1
def read
-
21
show
-
end
-
-
1
def update
-
8
card.new_card? ? create : handle { card.update! params[:card] }
-
end
-
-
1
def delete
-
4
handle { card.delete! }
-
end
-
-
# @deprecated
-
1
def asset
-
2
Rails.logger.info "Routing assets through Card. Recommend symlink from " \
-
'Deck to Card gem using "rake decko:update_assets_symlink"'
-
2
send_deprecated_asset
-
end
-
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
# PRIVATE METHODS
-
-
1
private
-
-
#-------( FILTERS )
-
-
1
before_action :setup, except: [:asset]
-
1
before_action :authenticate, except: [:asset]
-
1
before_action :load_mark, only: [:read]
-
1
before_action :load_card, except: [:asset]
-
1
before_action :load_action, only: [:read]
-
1
before_action :refresh_card, only: [:create, :update, :delete]
-
-
1
def setup
-
39
Card::Machine.refresh_script_and_style unless params[:explicit_file]
-
39
Card::Cache.renew
-
39
Card::Env.reset controller: self
-
end
-
-
1
def authenticate
-
39
Card::Auth.signin_with token: params[:token], api_key: params[:api_key]
-
end
-
-
1
def load_mark
-
23
params[:mark] = interpret_mark params[:mark]
-
end
-
-
1
def load_card
-
38
@card = Card.controller_fetch params
-
38
raise Card::Error::NotFound unless card
-
37
record_as_main
-
end
-
-
1
def load_action
-
28
card.select_action_by_params params
-
28
card.content = card.last_draft_content if params[:edit_draft] && card.drafts.present?
-
end
-
-
# TODO: refactor this away this when new layout handling is ready
-
1
def record_as_main
-
37
Card::Env[:main_name] = params[:main] || card&.name || ""
-
end
-
-
1
def refresh_card
-
16
@card = card.refresh
-
end
-
-
# ----------( HELPER METHODS ) -------------
-
-
1
def handle
-
16
Card::Env.success card.name
-
16
yield ? cud_success : raise(Card::Error::UserError)
-
end
-
-
# successful create, update, or delete act
-
1
def cud_success
-
13
success = Card::Env.success.in_context card.name
-
13
if success.reload?
-
reload # instruct JSON to reload
-
else
-
13
redirect_cud_success success
-
end
-
end
-
-
1
def show view=nil, status=200
-
33
card.action = :read
-
33
format = load_format
-
33
result = render_page format, view
-
33
status = format.error_status || status
-
33
respond format, result, status
-
end
-
-
1
def render_page format, view
-
33
view ||= view_from_params
-
33
card.act do
-
33
format.page self, view, Card::Env.slot_opts
-
end
-
end
-
-
1
def view_from_params
-
28
params[:view] || params[:v]
-
end
-
-
1
def handle_exception exception
-
5
raise exception if debug_exception?(exception)
-
5
@card ||= Card.new
-
5
error = Card::Error.report exception, card
-
5
show error.class.view, error.class.status_code
-
end
-
-
# TODO: move to exception object
-
1
def debug_exception? e
-
5
!e.is_a?(Card::Error::UserError) &&
-
!e.is_a?(ActiveRecord::RecordInvalid) &&
-
Card::Codename[:debugger] &&
-
Card[:debugger]&.content =~ /on/ # && !Card::Env.ajax?
-
end
-
-
1
class << self
-
1
def rescue_from_class *klasses
-
1
klasses.each do |klass|
-
10
rescue_from(klass) { |exception| handle_exception exception }
-
end
-
end
-
-
1
def rescue_all?
-
1
Cardio.config.rescue_all_in_controller
-
end
-
end
-
-
1
rescue_from_class(*Card::Error::UserError.user_error_classes)
-
1
rescue_from_class StandardError if rescue_all?
-
end